事情的起因是这样的。相信很多人都经历过这样一个过程,一个成熟的线上app版本需要更新一个系列新功能的时候,我们上线需要完成以下几个步骤:
1.测试环境下,测试人员测试新功能,并且连带需要测试线上稳定版本的主要老功能。
2.确保没问题以后,后台和app上生产环境,测试人员需要在把生产环境的新功能和老功能都测试一遍。(一般大的公司上线都在凌晨,测试人员、后台、app开发都需要等生产没有问题了才可以下班)
这么看来,即使是上线一个小功能,还需要把之前迭代很多版本的老功能都按照测试用例测试一遍。实在是劳民伤财。那么我们的自动化测试就派上用场了。每次小版本更新的时候,都配套写多个自动化测试用例。上线前后直接跑一整套的测试用例。如果出现问题,会直接指出哪里有问题。
Espresso测试框架是在Android测试支持库中的,提供了操作一个app的api来模拟用户的操作。Espresso测试可以运行在Android2.3.3及其更高版本的机器上。
第一步:在app的build.gradle里面添加依赖
def VERSION = '27.1.0'
def espressoVersion = '2.2.2'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:' + VERSION
implementation 'com.android.support:support-annotations:' + VERSION
implementation 'com.android.support:recyclerview-v7:' + VERSION
androidTestImplementation 'com.android.support.test.espresso:espresso-core:' + espressoVersion
androidTestImplementation('com.android.support.test.espresso:espresso-contrib:' +espressoVersion) {
transitive false
}
androidTestImplementation 'com.android.support:support-annotations:' + VERSION
androidTestImplementation 'com.android.support:recyclerview-v7:' + VERSION
}
第二步:在app项目的androidTestwen文件夹下面找到一个自动生成的测试用例类。你也可以自己创建一个用来测试的类。
第三步:话不多说直接上代码!
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Rule
public ActivityTestRule activityTestRule = new ActivityTestRule(MainActivity.class);
@Test
public void case1() {
//进入case1(单选题,我最喜欢吃的食物是什么?,正确答案是:beer 啤酒) 进来先选择选项一、二、三。
//最后断言 看最终选择的是不是正确答案 beer 啤酒
Espresso.onView(withId(R.id.tvCase1)).perform(click());
Espresso.onView(withId(R.id.rb1)).perform(click());
Espresso.onView(withId(R.id.rb2)).perform(click());
Espresso.onView(withId(R.id.rb3)).perform(click());
Espresso.onView(withId(R.id.tvFavoriteFood)).check(matches(withText("beer")));
}
@Test
public void case2() {
//进入case1(单选题,我最喜欢吃的食物是什么?,正确答案是:beer 啤酒) 进来先选择选项一、二、三、四。
//最后断言 看最终选择的是不是正确答案 beer 啤酒
Espresso.onView(withId(R.id.tvCase1)).perform(click());
Espresso.onView(withId(R.id.rb1)).perform(click());
Espresso.onView(withId(R.id.rb2)).perform(click());
Espresso.onView(withId(R.id.rb3)).perform(click());
Espresso.onView(withId(R.id.rb4)).perform(click());
Espresso.onView(withId(R.id.tvFavoriteFood)).check(matches(withText("beer")));
}
}
测试用例很简单进入测试界面。选择最喜欢的食物,正确答案是beer 啤酒。case1选择的是第三个选项 Fried chicken。case2选择的是第四个选项 beer。两个case结束的时候,我都进行了断言匹配选项是不是“beer”。
不知道怎么运行的同学请看截图(在想运行的类上面右击选择Run “你的类”):
运行case(不得不说作为谷歌的亲儿子,espresso的响应速度可谓非常快的):
运行后结果如图:
可以看出来日志显示“2 tests done:1 failed.” 也就是说case1失败,case2成功。符合原先的的代码逻辑,是我希望看到的结果。红框上面也提示了“with text :is "beer" doesn't match the selected view”.告诉我case1的最终选择不是我想要的“beer”这个答案。
appium优点:
appium缺点:
那么接下来开始:
第一步,配置环境,安装sdk,nodejs,appium客户端等。传送门 https://www.jianshu.com/p/9412e4eebaae
第二步,在项目中添加一个Java library的module。添加目录和文件。
第三步,上代码
public class AndroidContactsTest {
//Driver
private AndroidDriver driver;
/**
* 配置启动driver
*
* @throws Exception
*/
@Before
public void setUp() throws Exception {
File classpathRoot = new File(System.getProperty("user.dir"));
//app的目录
File appDir = new File(classpathRoot, "/src/main/java/apps/release");
//app的名字,对应你apps目录下的文件
File app = new File(appDir, "app-release.apk");
//创建Capabilities
DesiredCapabilities capabilities = new DesiredCapabilities();
//设置要调试的模拟器的名字
capabilities.setCapability("deviceName", "Redmi 4X");
//设置模拟器的系统版本
capabilities.setCapability("platformVersion", "7.1.2");
//设置app的路径
capabilities.setCapability("app", app.getAbsolutePath());
//设置app的包名
capabilities.setCapability("appPackage", "com.ironman.autotestappium");
//设置app的启动activity
capabilities.setCapability("appActivity", ".MainActivity");
//设置app可以输入中文字符
capabilities.setCapability("unicodeKeyboard", "True");
capabilities.setCapability("resetKeyboard", "True");
//启动driver
driver = new AndroidDriver<>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
}
@After
public void tearDown() throws Exception {
//测试完毕,关闭driver,不关闭将会导致会话还存在,下次启动就会报错
driver.quit();
}
@Test
public void case1() {
//进入case1(单选题,我最喜欢吃的食物是什么?,正确答案是:beer 啤酒) 进来先选择选项一、二、三。
//最后断言 看最终选择的是不是正确答案 beer 啤酒
driver.findElementById("com.ironman.autotestappium:id/tvCase1").click();
driver.findElementById("com.ironman.autotestappium:id/rb1").click();
driver.findElementById("com.ironman.autotestappium:id/rb2").click();
driver.findElementById("com.ironman.autotestappium:id/rb3").click();
String favoriteFood = driver.findElementById("com.ironman.autotestappium:id/tvFavoriteFood").getText();
assertEquals("beer", favoriteFood);
}
@Test
public void case2() {
//进入case1(单选题,我最喜欢吃的食物是什么?,正确答案是:beer 啤酒) 进来先选择选项一、二、三、四。
//最后断言 看最终选择的是不是正确答案 beer 啤酒
driver.findElementById("com.ironman.autotestappium:id/tvCase1").click();
driver.findElementById("com.ironman.autotestappium:id/rb1").click();
driver.findElementById("com.ironman.autotestappium:id/rb2").click();
driver.findElementById("com.ironman.autotestappium:id/rb3").click();
driver.findElementById("com.ironman.autotestappium:id/rb4").click();
String favoriteFood = driver.findElementById("com.ironman.autotestappium:id/tvFavoriteFood").getText();
assertEquals("beer", favoriteFood);
}
@Test
public void case3() {
driver.findElementById("com.ironman.autotestappium:id/tvJump").click();
driver.findElementByXPath("//*[@text='登录']").click();
driver.findElementById("com.tencent.mm:id/hz").sendKeys("17600000000");
driver.findElementById("com.tencent.mm:id/alr").click();
driver.findElementById("com.tencent.mm:id/hz").sendKeys("123456");
driver.findElementById("com.tencent.mm:id/alr").click();
driver.pressKey(new KeyEvent(AndroidKey.BACK));
}
}
运行case(相比较espresso,这测试速度真心是。。。。反正急性子的人慎用,另外感谢 特效大神 过志鑫 同学协助完成录屏部分)
运行后的结果如图:
相比较espresso,appium的输出日志就清晰很多了。case1、case2、case3全部的三个测试用例都展示了出来,并且告诉你case1失败(断言期待结果是“beer”,结果是“Fried chicken”),case2、case3成功。
appium总体来说,除了响应速度略微慢了点,其他不管是测试用例实现方式,应用的范围、日志生成的表现形式都是优于espresso的。但如果是轻量级测试UI方面的话,espresso也是一个不错的选择。
最后贴上附上github的Demo.习惯的老铁可以点一波关注,或者双击666。