测试

1.应用程序的测试 (测试是软件开发中非常重要的一个环节)
* 黑盒测试
(不需要写代码),只需要对功能需求和业务逻辑熟悉,并不知道软件是什么语言开发的,也不关心内部逻辑,所以对于他们来说,就像是个黑色的盒子.例如一款游戏公测之前,会邀请一部分人进行小范围的内测,那你就是一个免费的黑盒测试人员    
1)包括本身自带的monkey,Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中
2) robotium与appium,这些工具用于黑盒的自动化测试。可以在有源码或者只有APK 的情况下对目标应用进行测试。提供了模仿用户操作行为的API,比如在某个控件上点击,输入Text 等等。         
 * 白盒测试(需要写代码)
Android在SDK中集成了JUnit框架。所以,你可以基于JUNIT框架进行安卓的白盒测试代码开发
    * 所有测试代码一定要抛出异常            
         * A ndroid创建测试工程的步骤:
            * 创建Android Test Project,然后选择原项目
            * 测试类必须继承自AndroidTestCase
            * 所有的方法都要以test开始
            * 所有的异常都要抛出
            * 最后运行Android JUnit Test
      注:若在原工程测试,则另建立一个测试包,写测试逻辑代码,但要在清单文件中加配置,事例如下:
       在AndroidManifest.xml文件中进行配置
     1.在 < manifest>标签中配置指令集
    
     2.在 < application>标签中配置使用到的类库
    
     
     
  1. public class TestBusiness extends AndroidTestCase {
  2. public void testGetSub() throws Exception{
  3. Business business =new Business();
  4. int sum = business.getSum(2, 3);
  5. //assertEquals(expected, actual):第一个参数expected:指期望的值;第二个参数actual:返回的结果值
  6. assertEquals(5, sum);
  7. }
  8. }

2.测试相关概念 
2.1   根据测试的粒度可以划分出几种测试方法
    1.  单元测试(方法测试)  junit test
     是对编码的验证,保证编码无误,也就是保证某个单元(可以是页面,可以是某个流程等等)被正确的编码。
    2.  集成测试,几个模块进行测试 integration test
    3.  系统测试, system test


2.2   根据测试的力度划分
    1.  压力测试 pressure test(12306)
 * adb shell
 * monkey 2000

    2.  冒烟测试 smoke test(重复操作)

3.APP的测试分为许多点,其中的部分:

 3.1 软件的权限测试。如连网,发送信息,打开摄像头等操作。

 3.2 安装与卸载安全性。如安装是否正确,卸载是否干净等。

 3.3 数据安全性。 如密码不会以明文形式显示,密码是否容易被解密等。

 3.4 通话安全性处理。如软件在运行过程中,接到电话,是否能够将软件运行状态保存,并优先处理电话。

 3.5 UI测试。软件运行效果图是否与设计效果图一致。

 3.6 功能测试。是对功能设计的验证,按照设计思路,运行软件,观察各个功能是否能够正确执行。

 3.7 后台切换。如将运行中的APP切换到后台之后,当再次打开时是否还为当前显示页面。

 3.8  结合测试,是对详细设计的验证,保证各个单元串起来之后,能够完成基本的业务流转。

 3.9  用户体验,是对需求分析的验证,保证系统就是用户想要的东西。


4.Android测试框架

4.1 Robotium

毫无疑问,早期Android世界里用得最为广泛的测试框架就是Robotium。它与Selenium的Android版本有类似之处,可以让测试API更简单。

Robotium是一个开源的库,基于JUnit扩展了大量关于Android UI的有效测试方法。它为 Android 应用程序(原生和混合)和web 测试提供了功能强大且可靠的自动化黑盒测试用例。只要源码可用,利用Robotium,你就可以编写功能测试、系统测试和验收测试场景,并执行测试。

     
     
  1. //Public void 方法
  2. public void testRecorded() throws Exception {
  3. //等待文本“Hello”显示
  4. if (solo.waitForText("Hello!")) {
  5. //找到R类id标识符为"Sign in"的控件-然后点击它
  6. solo.clickOnView(solo.findViewById("com.twitter.android.R.id.sign_in"));
  7. //找到用户名的控件并输入登陆用户名
  8. solo.enterText((EditText) solo.findViewById("com.twitter.android.R.id.login_username"),"username");
  9. //找到密码的控件并输入登陆密码
  10. solo.enterText((EditText) solo.findViewById("com.twitter.android.R.id.login_password"),"password");
  11. //找到登陆按钮,点击登陆
  12. solo.clickOnView(solo.findViewById("com.twitter.android.R.id.login_login"));
  13. //等待登陆完成
  14. solo.waitForActivity("HomeTabActivity");
  15. }
  16. //激活文本域来编写一个tweet
  17. solo.clickOnView(solo.findViewById("com.twitter.android.R.id.menu_compose_tweet"));
  18. //编辑tweet
  19. solo.enterText((EditText) solo.findViewById("com.twitter.android.R.id.edit"), "Testdroid");
  20. //推送tweet中!
  21. solo.clickOnView(solo.findViewById("com.twitter.android.R.id.composer_post"));
  22. }

Testdroid Recorder 是一个很棒的记录工具,它基于Robotium来创建测试脚本为你带来方便。通过在真正设备上执行实际操作,它可以记录每个步骤或者你执行的动作,然后转换为Javascript供你进一步修改。

此外,你也可以完全下载和使用我们的扩展库——ExtSolo。它包括了一些尚未合并到Robotium的有用方法,比如:

  • 支持任意分辨率的x、y点击自动缩放
  • 多路径拖拽
  • 测试失败时自动截屏
  • 模拟位置
  • 修改设备语言
  • 控制WiFi连接

4.2 uiautomator

Robotium这个框架不错但稍显简单。uiautomator可以让你在测试Android app和游戏时实现更多操作。Google的测试框架(译者注:uiautomator是Google在SDK4.0以后推出的自动化解决方案)支持在一个或多个设备上测试本地Android app用户界面(UI)。uiautomator的另一个优点是它运行JUnit测试用例时有特权,意味着测试用例可以跨进程。它还提供了五个不同的类给开发者使用,包括:

         
         
  1. com.android.uiautomator.core.UiCollection;
  2. com.android.uiautomator.core.UiDevice;
  3. com.android.uiautomator.core.UiObject;
  4. com.android.uiautomator.core.UiScrollable;
  5. com.android.uiautomator.core.UiSelector
由于它出现的时间点关系,它只适用于与API级别为16 (译者注:相当于SDK4.1) 或更高版本的Android设备。Uiautomator的另一个缺点是它不支持webview,没有办法到直接获取到Android的UI对象。
     
     
  1. //Public void 方法
  2. public void testSignInAndTweet() throws Exception {
  3. //启动应用
  4. getUiDevice().wakeUp();
  5. //点击Home键以保证回到主屏
  6. getUiDevice().pressHome();
  7. //选择“应用”并点击
  8. new UiObject(new UiSelector().description("Apps")).click();
  9. //选择“Twitter”并点击
  10. new UiObject(new UiSelector().text("Twitter")).click();
  11. //定位并选择“登陆”
  12. UiSelector signIn = new UiSelector().text("Sign In");
  13. //如果按钮可用,则点击
  14. UiObject signInButton = new UiObject(signIn);
  15. if (signInButton.exists()) {
  16. signInButton.click();
  17. //设置用户名
  18. new UiObject(new
  19. UiSelector().className("android.widget.EditText").instance(0)).setText("username");
  20. new UiObject(new
  21. UiSelector().className("android.widget.EditText").instance(1)).setText("password");
  22. new UiObject(new UiSelector().className("android.widget.Button").
  23. text("Sign In").instance(0)).click();
  24. //等待登陆处理
  25. getUiDevice().waitForWindowUpdate(null, 2000);
  26. // 等待主窗口
  27. getUiDevice().waitForWindowUpdate(null, 30000);
  28. }
  29. new UiObject(new UiSelector().description("New tweet")).click();
  30. //编辑一个新tweet
  31. new UiObject(new UiSelector().className("android.widget.LinearLayout").instance(8)).
  32. setText("Awesome #Testdroid!");
  33. //推送tweet
  34. new UiObject(new UiSelector().text("Tweet")).click();
  35. }

4.3 Espresso

Espresso是一个最新的Android自动化测试框架,由Google开源,它可以帮助开发和测试推敲UI的设计。Espresso有一个很小、可预测的且容易上手的API,它构建在Android instrumentation 框架的顶层。你可以利用它快速写出简洁可靠的Android UI测试用例。它支持API级别为8(Froyo)、10 (Gingerbread)和 15 (Ice Cream Sandwich)及之后的设备。

它相当可靠,与UI线程同步并且速度快,因为没有必要做任何休眠等待的操作(当app空闲时测试运行在同一个毫秒级别)。不过它同样不支持webview。

      
      
  1. public void testEspresso() {
  2. // Check if view with the text 'Hello.' is shown
  3. //如果带有文本“Hello”的控件显示,则点击
  4. onView(withText("Hello.")).check(matches(isDisplayed()));
  5. // R class ID identifier for 'Sign in' - and click it
  6. //找到R类id标识符为"Sign in"的控件-然后点击它
  7. onView(withId(getInstrumentation().getTargetContext().getResources()
  8. .getIdentifier("com.twitter.android:id/sign_in", null, null))).perform(click());
  9. // R class ID identifier for entering username
  10. //找到用户名的控件并输入登陆用户名
  11. onView(withId(getInstrumentation().getTargetContext().getResources()
  12. .getIdentifier("com.twitter.android:id/login_username", null, null))).perform((typeText("username")));
  13. // R class ID identifier for entering password
  14. //找到密码的控件并输入登陆密码
  15. onView(withId(getInstrumentation().getTargetContext().getResources()
  16. .getIdentifier("com.twitter.android:id/login_password", null, null))).perform((typeText("password")));
  17. // R class ID identifier for clicking log in
  18. //找到登陆按钮,点击登陆
  19. onView(withId(getInstrumentation().getTargetContext().getResources()
  20. .getIdentifier("com.twitter.android:id/login_login", null, null))).perform(click());
  21. // Activate the text field to compose a tweet
  22. //激活文本域来编写一个tweet
  23. onView(withId(getInstrumentation().getTargetContext().getResources()
  24. .getIdentifier("com.twitter.android:id/menu_compose_tweet", null, null))).perform(click());
  25. // Type the tweet
  26. //编辑tweet
  27. onView(withId(getInstrumentation().getTargetContext().getResources()
  28. .getIdentifier("com.twitter.android:id/edit", null, null))).perform((typeText(”#Testdroid")));
  29. // Tweeting!
  30. //推送tweet中!
  31. onView(withId(getInstrumentation().getTargetContext().getResources()
  32. .getIdentifier("com.twitter.android:id/composer_post", null, null))).perform(click());
  33. }

4.4 Calabash

Calabash是一个跨平台的自动化测试框架,支持Android、iOS原生和混合的应用测试。Calabash的语法通俗易懂,甚至技术零基础的人也能为运行在各种移动平台上的应用编写和执行自动化验收测试用例。Calabash的测试用例编写是基于Cucumber(译者注:Calabash的底层实现是Cucumber,它是一种BDD测试框架),然后在运行时将脚本转换为Robotium或者Frank。它支持大约80种自然语言命令(控制器),并且可以用Ruby或Java实现新的控制器。

       
       
  1. Feature: Login feature
  2. Scenario: As a valid user I can log into my app
  3. I wait for text &quot;Hello&quot;
  4. Then I press view with id &quot;Sign in&quot;
  5. Then I enter text &quot;username&quot; into &quot;login_username&quot;
  6. Then I enter text &quot;password&quot; into &quot;login_password&quot;
  7. Then I wait for activity &quot;HomeTabActivity&quot;
  8. Then I press view with id &quot;menu_compose_tweet&quot;
  9. Then I enter text &quot;Testdroid&quot; into field with id &quot;edit&quot;
  10. Then I press view with id &quot;composer_post&quot;

4.5  Appium

Appium是一个移动自动化测试框架(工具),可支持iOS和Android的原生、混合的移动web应用测试。它内部采用Selenium WebDriverJSON Wire Protocol来与iOS和Android app交互。它通过驱动uiautomator(API级别高于等于16)和Seledroid(API级别低于16)支持Android,驱动UIAutomation来支持iOS,利用Selenium driver来支持 Android和iOS都有的移动web。

Appium最大的一个优点就是几乎可以使用任何一种语言(比如Java、Objective-C、JavaScript、PHP、Ruby、Python、C#等)来编写Appium脚本,不受工具选择的限制,兼容两个最重要的平台(Android和iOS),安装和配置设备来测试等也自由许多。而且如果你对Selenium很熟悉,那么对你而言使用Appium测试移动app轻而易举。他们使用的是相同的WebDriver,且DesiredCapabilities(译者注:DesiredCapabilities是由客户端发送给Appium服务器端用来告诉服务器去启动哪种会话的一套键值对集合)的使用方式相同。因此在Appium上配置运行一个应用与在Selenium上有非常多相似之处。


它的优点:

  • 开源;
  • 支持Native App、Hybird App、Web App;
  • 支持Android、iOS、Firefox OS;
  • Server也是跨平台的,你可以使用Mac OS X、Windows或者Linux;

它的哲理是:

  • 用Appium自动化测试不需要重新编译App;
  • 支持很多语言来编写测试脚本,Java、Javascript、PHP、Python、C#、Ruby等主流语言;
  • 不需要为了自动化测试来重造轮子,因为扩展了WebDriver。(WebDriver是测试WebApps的一种简单、快速的自动化测试框架,所以有Web自动化测试经验的测试人员可以直接上手);
  • 移动端自动化测试应该是开源的;

它的设计理念:

  • Client/Server架构,运行的时候Server端会监听Client端发过来的命令,翻译这些命令发送给移动设备或模拟器,然后移动设备或模拟器做出响应的反应。正是因为这种架构,所以Client可以使用Appium client libraries多种语言的测试脚本,而且Server端完全可以部署在服务器上,甚至云服务器。
  • Session,每个Client连接到Server以后都会有一个Session ID,而且Client发送命令到Server端都需要这个Session ID,因为这个seesion id代表了你所打开的浏览器或者是移动设备的模拟器。所以你甚至可以打开N个Session,同时测试不同的设备或模拟器。
  • Desired Capabilities,其实就是一个键值对,设置一些测试的相关信息来告诉Server端,我们需要测试iOS、还是Android,或者换是WebApp等信息。
  • Appium Server是Node.js写的,所以可以直接用NPM来进行安装。
  • Appium Clients,Mac OS和Win下提供GUI,不需要装Node.js,方便测试人员操作。

相关限制:

  • 如果你在Windows使用Appium,你没法使用预编译专用于OS X的.app文件,因为Appium依赖OS X专用的库来支持iOS测试,所以在Windows平台你不能测试iOS Apps。这意味着你只能通过在Mac上来运行iOS测试。
        
        
  1. # wait for hello
  2. #等待hello出现
  3. sleep(3)
  4. textFields = driver.find_elements_by_tag_name('textField')
  5. assertEqual(textFields[0].get_attribute("value"), "Hello")
  6. # click sign-in button
  7. #点击登陆按钮
  8. driver.find_elements_by_name('Sign in')[0].click()
  9. # find the text fields again, and enter username and password
  10. #找到文本域,然后键入用户名和密码
  11. textFields = driver.find_elements_by_tag_name('textField')
  12. textFields[0].send_keys("twitter_username")
  13. textFields[1].send_keys("passw0rd")
  14. # click the Login button (the first button in the view)
  15. #点击登陆按钮(控件中的第一个按钮)
  16. driver.find_elements_by_tag_name('button')[0].click()
  17. # sleep
  18. #休眠
  19. sleep(3)
  20. # click the first button with name "Compose"
  21. #点击名字为"Compose"的第一个按钮
  22. driver.find_elements_by_name('Compose')[0].click()
  23. # type in the tweet message
  24. #键入tweet消息内容
  25. driver.find_elements_by_tag_name('textField')[0].send_keys(”#Testdroid is awesome!")
  26. # press the Send button
  27. #点击发送按钮
  28. driver.find_elements_by_name('Send')[0].click()
  29. # exit
  30. #退出
  31. driver.quit()

5.测试案例
         
         
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout android:id="@+id/activity_main"
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:orientation="vertical"
  8. android:padding="20dp"
  9. tools:context="cn.mycommons.testcase.MainActivity">
  10. <EditText
  11. android:id="@+id/edtUserName"
  12. android:layout_width="match_parent"
  13. android:layout_height="50dp"
  14. android:hint="Input user name" />
  15. <EditText
  16. android:id="@+id/edtPasswd"
  17. android:layout_width="match_parent"
  18. android:layout_height="50dp"
  19. android:hint="Input password"
  20. android:contentDescription="Input password"
  21. android:inputType="textPassword" />
  22. <Button
  23. android:id="@+id/btnLogin"
  24. android:layout_width="match_parent"
  25. android:layout_height="50dp"
  26. android:text="Login" />
  27. </LinearLayout>
          
          
  1. package cn.mycommons.testcase;
  2. import android.content.Intent;
  3. import android.os.Bundle;
  4. import android.support.v7.app.AppCompatActivity;
  5. import android.view.View;
  6. import android.widget.Button;
  7. import android.widget.EditText;
  8. import android.widget.Toast;
  9. public class MainActivity extends AppCompatActivity {
  10. EditText edtUserName;
  11. EditText edtPasswd;
  12. Button btnLogin;
  13. String userName;
  14. String passwd;
  15. @Override
  16. protected void onCreate(Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. setContentView(R.layout.activity_main);
  19. edtUserName = (EditText) findViewById(R.id.edtUserName);
  20. edtPasswd = (EditText) findViewById(R.id.edtPasswd);
  21. btnLogin = (Button) findViewById(R.id.btnLogin);
  22. btnLogin.setOnClickListener(new View.OnClickListener() {
  23. @Override
  24. public void onClick(View view) {
  25. userName = edtUserName.getText().toString();
  26. passwd = edtPasswd.getText().toString();
  27. if (check(userName, passwd)) {
  28. doLogin(userName, passwd);
  29. }
  30. }
  31. });
  32. }
  33. boolean check(String userName, String passwd) {
  34. do {
  35. if (userName.length() < 5) {
  36. showToast("User name invalidate");
  37. break;
  38. }
  39. if (passwd.length() < 5) {
  40. showToast("Password invalidate");
  41. break;
  42. }
  43. return true;
  44. } while (false);
  45. return false;
  46. }
  47. void doLogin(String userName, String passwd) {
  48. if ("admin".equals(userName) && "admin".equals(passwd)) {
  49. showToast("Login success");
  50. startActivity(new Intent(this, SuccessActivity.class));
  51. } else {
  52. showToast("Login fail");
  53. }
  54. }
  55. void showToast(String msg) {
  56. Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
  57. }
  58. }

5.1 Monkey测试     

Monkey只是检查使用下shell命令即可。

         
         
  1. adb shell monkey -p cn.mycommons.testcase -v 50000

5.2 Monkey Runner测试      

Monkey Runner提供的是一个python文件,然后调用monkeyrunner命令即可。

         
         
  1. $ monkeyrunner test_case.py
          
          
  1. # Imports the monkeyrunner modules used by this program
  2. from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
  3. # Connects to the current device, returning a MonkeyDevice object
  4. print 'wait for device connection.'
  5. device = MonkeyRunner.waitForConnection()
  6. print 'connect device success.'
  7. # Takes a screenshot
  8. result = device.takeSnapshot()
  9. print 'takeSnapshot success.'
  10. # Writes the screenshot to a file
  11. result.writeToFile('./test_case1.png','png')
  12. print 'save image to file success.'
  13. # input user name
  14. device.touch(200,380,'DOWN_AND_UP')
  15. print 'touch user name'
  16. for x in xrange(1,100):
  17. device.press("KEYCODE_DEL",'DOWN_AND_UP')
  18. print 'delete user name'
  19. device.type("admin")
  20. print 'input admin to user name'
  21. # input passwd
  22. device.touch(200,500,'DOWN_AND_UP')
  23. print 'touch password'
  24. for x in xrange(1,100):
  25. device.press("KEYCODE_DEL",'DOWN_AND_UP')
  26. print 'delete password'
  27. device.type("admin")
  28. print 'input admin to password'
  29. # press login button
  30. device.touch(200,680,'DOWN_AND_UP')
  31. print 'press login button'
  32. MonkeyRunner.sleep(2)
  33. # Takes a screenshot
  34. result = device.takeSnapshot()
  35. print 'takeSnapshot success.'
  36. # Writes the screenshot to a file
  37. result.writeToFile('./test_case2.png','png')
  38. print 'save image to file success.'

5.3 UiAutomator测试

            
            
  1. package cn.mycommons.testcase;
  2. import android.content.Context;
  3. import android.content.Intent;
  4. import android.os.Build;
  5. import android.support.test.InstrumentationRegistry;
  6. import android.support.test.filters.SdkSuppress;
  7. import android.support.test.runner.AndroidJUnit4;
  8. import android.support.test.uiautomator.By;
  9. import android.support.test.uiautomator.UiDevice;
  10. import android.support.test.uiautomator.UiObject;
  11. import android.support.test.uiautomator.UiObjectNotFoundException;
  12. import android.support.test.uiautomator.UiSelector;
  13. import android.support.test.uiautomator.Until;
  14. import org.hamcrest.Matchers;
  15. import org.junit.Before;
  16. import org.junit.Test;
  17. import org.junit.runner.RunWith;
  18. import static org.junit.Assert.assertThat;
  19. @RunWith(AndroidJUnit4.class)
  20. @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN_MR2)
  21. public class MainActivityTest {
  22. private static final String BASIC_SAMPLE_PACKAGE = "cn.mycommons.testcase";
  23. private static final int LAUNCH_TIMEOUT = 5000;
  24. private static final String STRING_TO_BE_TYPED = "UiAutomator";
  25. private UiDevice mDevice;
  26. @Before
  27. public void before() {
  28. mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
  29. mDevice.pressHome();
  30. // Wait for launcher
  31. final String launcherPackage = mDevice.getLauncherPackageName();
  32. assertThat(launcherPackage, Matchers.notNullValue());
  33. mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT);
  34. Context context = InstrumentationRegistry.getContext();
  35. final Intent intent = context.getPackageManager().getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE);
  36. intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
  37. context.startActivity(intent);
  38. // Wait for the app to appear
  39. mDevice.wait(Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT);
  40. }
  41. @Test
  42. public void testLogin1() throws UiObjectNotFoundException {
  43. UiObject login = mDevice.findObject(new UiSelector().text("Login"));
  44. UiObject edtUserName = mDevice.findObject(new UiSelector().text("Input user name"));
  45. UiObject edtPasswd = mDevice.findObject(new UiSelector().descriptionContains("Input password"));
  46. edtUserName.clearTextField();
  47. edtPasswd.clearTextField();
  48. edtUserName.setText("admin");
  49. edtPasswd.setText("admin");
  50. login.click();
  51. mDevice.waitForWindowUpdate(BuildConfig.FLAVOR, 3000);
  52. }
  53. @Test
  54. public void testLogin2() throws UiObjectNotFoundException {
  55. UiObject login = mDevice.findObject(new UiSelector().text("Login"));
  56. UiObject edtUserName = mDevice.findObject(new UiSelector().text("Input user name"));
  57. UiObject edtPasswd = mDevice.findObject(new UiSelector().descriptionContains("Input password"));
  58. edtUserName.clearTextField();
  59. edtPasswd.clearTextField();
  60. edtUserName.setText("");
  61. edtPasswd.setText("");
  62. login.click();
  63. }
  64. @Test
  65. public void testLogin3() throws UiObjectNotFoundException {
  66. UiObject login = mDevice.findObject(new UiSelector().text("Login"));
  67. UiObject edtUserName = mDevice.findObject(new UiSelector().text("Input user name"));
  68. UiObject edtPasswd = mDevice.findObject(new UiSelector().descriptionContains("Input password"));
  69. edtUserName.clearTextField();
  70. edtPasswd.clearTextField();
  71. edtUserName.setText("abc");
  72. edtPasswd.setText("");
  73. login.click();
  74. }
  75. @Test
  76. public void testLogin4() throws UiObjectNotFoundException {
  77. UiObject login = mDevice.findObject(new UiSelector().text("Login"));
  78. UiObject edtUserName = mDevice.findObject(new UiSelector().text("Input user name"));
  79. UiObject edtPasswd = mDevice.findObject(new UiSelector().descriptionContains("Input password"));
  80. edtUserName.clearTextField();
  81. edtPasswd.clearTextField();
  82. edtUserName.setText("");
  83. edtPasswd.setText("abc");
  84. login.click();
  85. }
  86. @Test
  87. public void testLogin5() throws UiObjectNotFoundException {
  88. UiObject login = mDevice.findObject(new UiSelector().text("Login"));
  89. UiObject edtUserName = mDevice.findObject(new UiSelector().text("Input user name"));
  90. UiObject edtPasswd = mDevice.findObject(new UiSelector().descriptionContains("Input password"));
  91. edtUserName.clearTextField();
  92. edtPasswd.clearTextField();
  93. edtUserName.setText("abc");
  94. edtPasswd.setText("abc");
  95. login.click();
  96. }
  97. @Test
  98. public void testLogin6() throws UiObjectNotFoundException {
  99. UiObject login = mDevice.findObject(new UiSelector().text("Login"));
  100. UiObject edtUserName = mDevice.findObject(new UiSelector().text("Input user name"));
  101. UiObject edtPasswd = mDevice.findObject(new UiSelector().descriptionContains("Input password"));
  102. edtUserName.clearTextField();
  103. edtPasswd.clearTextField();
  104. edtUserName.setText("abcedf");
  105. edtPasswd.setText("abc");
  106. login.click();
  107. }
  108. @Test
  109. public void testLogin7() throws UiObjectNotFoundException {
  110. UiObject login = mDevice.findObject(new UiSelector().text("Login"));
  111. UiObject edtUserName = mDevice.findObject(new UiSelector().text("Input user name"));
  112. UiObject edtPasswd = mDevice.findObject(new UiSelector().descriptionContains("Input password"));
  113. edtUserName.clearTextField();
  114. edtPasswd.clearTextField();
  115. edtUserName.setText("abcedf");
  116. edtPasswd.setText("abcedf");
  117. login.click();
  118. }
  119. }

54 Espressor测试

              
              
  1. package cn.mycommons.testcase;
  2. import android.support.test.espresso.Espresso;
  3. import android.support.test.espresso.action.ViewActions;
  4. import android.support.test.espresso.matcher.ViewMatchers;
  5. import android.support.test.rule.ActivityTestRule;
  6. import android.support.test.runner.AndroidJUnit4;
  7. import org.junit.Rule;
  8. import org.junit.Test;
  9. import org.junit.runner.RunWith;
  10. @RunWith(AndroidJUnit4.class)
  11. public class MainActivityEspressoTest {
  12. @Rule
  13. public ActivityTestRule<MainActivity> testRule = new ActivityTestRule<>(MainActivity.class);
  14. @Test
  15. public void testLogin() {
  16. Espresso.onView(ViewMatchers.withContentDescription(R.id.edtUserName)).perform(ViewActions.typeText("admin"));
  17. Espresso.onView(ViewMatchers.withId(R.id.edtPasswd)).perform(ViewActions.typeText("admin"));
  18. Espresso.onView(ViewMatchers.withId(R.id.btnLogin)).perform(ViewActions.click());
  19. }
  20. @Test
  21. public void testLogin1() {
  22. Espresso.onView(ViewMatchers.withId(R.id.edtUserName)).perform(ViewActions.typeText(""));
  23. Espresso.onView(ViewMatchers.withId(R.id.edtPasswd)).perform(ViewActions.typeText(""));
  24. Espresso.onView(ViewMatchers.withId(R.id.btnLogin)).perform(ViewActions.click());
  25. }
  26. @Test
  27. public void testLogin2() {
  28. Espresso.onView(ViewMatchers.withId(R.id.edtUserName)).perform(ViewActions.typeText("abc"));
  29. Espresso.onView(ViewMatchers.withId(R.id.edtPasswd)).perform(ViewActions.typeText(""));
  30. Espresso.onView(ViewMatchers.withId(R.id.btnLogin)).perform(ViewActions.click());
  31. }
  32. @Test
  33. public void testLogin3() {
  34. Espresso.onView(ViewMatchers.withId(R.id.edtUserName)).perform(ViewActions.typeText(""));
  35. Espresso.onView(ViewMatchers.withId(R.id.edtPasswd)).perform(ViewActions.typeText("abc"));
  36. Espresso.onView(ViewMatchers.withId(R.id.btnLogin)).perform(ViewActions.click());
  37. }
  38. @Test
  39. public void testLogin4() {
  40. Espresso.onView(ViewMatchers.withId(R.id.edtUserName)).perform(ViewActions.typeText("abc"));
  41. Espresso.onView(ViewMatchers.withId(R.id.edtPasswd)).perform(ViewActions.typeText("abc"));
  42. Espresso.onView(ViewMatchers.withId(R.id.btnLogin)).perform(ViewActions.click());
  43. }
  44. @Test
  45. public void testLogin5() {
  46. Espresso.onView(ViewMatchers.withId(R.id.edtUserName)).perform(ViewActions.typeText("abcdef"));
  47. Espresso.onView(ViewMatchers.withId(R.id.edtPasswd)).perform(ViewActions.typeText("abcdef"));
  48. Espresso.onView(ViewMatchers.withId(R.id.btnLogin)).perform(ViewActions.click());
  49. }
  50. }

6. 自动化测试总结
  • Monkey 
    准确来说,这不算是自动化测试,因为其只能产生随机的事件,无法按照既定的步骤操作;

  • Monkeyrunner 
    优点:操作最为简单,可以录制测试脚本,可视化操作; 
    缺点:主要生成坐标的自动化操作,移植性不强,功能最为局限,上面代码中已经显示出来,完全使用的数字坐标,移植到另外一个设备,则不能运行。

  • UiAutomator 
    优点:可以对所有操作进行自动化,操作简单; 
    缺点:Android版本需要高于4.3,无法根据控件ID操作,相对来说功能较为局限,但也够用了;

  • Espresso 
    优点:主要针对某一个APK进行自动化测试,APK可以有源码,也可以没有源码,功能强大; 
    缺点:针对APK操作,因此操作相对复杂;

总结:测试某个APK,可以选择Espresso;测试过程可能涉及多个APK,选择UiAutomator;一些简单的测试,选择Monkeyrunner;




了解更多的测试相关的知识,请参考以下资源:
在Android Studio中进行单元测试和UI测试  http://www.jianshu.com/p/03118c11c199
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值