Github地址
相关jar包下载
Robotium中各个类的用途
类 |
用途 |
方法 |
By |
查询条件类,类似于UIAutomator的By类。只是,Robotium的By只用于查询WebElement对象. 例如,根据id获取web元素,或根据name获取web元素 |
8 |
Illustration |
用于在屏幕上画点到点的路径 |
2 |
Illustration.Builder |
Illustration的工厂类 |
3 |
RobotiumUtils |
用于对查找到的View列表,进行进一步的过滤和排序。 |
8 |
Solo |
Robotium的核心类,用于查找,滚屏,点击,等待等具体操作 |
216 |
Solo.Config |
Solo的内容类,用于Solo的默认设置。例如截图文件类型,log tag等,共12个成员变量 |
0 |
SystemUtils |
用于控制WIFI和移动数据接口的开关 |
2 |
Timeout |
用于设置/获取Timeout |
4 |
WebElement |
借由By对象查询到的WebView中的控件对象 |
17 |
Condition |
接口 |
1 |
ScreenshotFileType |
支持两种文件类型,JPEN和PNG |
0 |
除Solo外,其他都是辅助类
Solo中除了构造函数外,共包含216个方法,分类看
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190826135551802.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTAzNTY3Njg=,size_16,color_FFFFFF,t_70)
小试牛刀
Robotium在Getting-Started中提供了简单示例。下载AS对应的项目,app/src/androidTest/java/com.example.android.notepad/NotePadTest.java,右键Run即可
测试1
我们在下载下来的项目基础上写一个关于登录的测试
首先新建MainActivity
public class MainActivity extends Activity {
private EditText etName;
private EditText etPassword;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etName = (EditText) findViewById(R.id.et_name);
etPassword = (EditText) findViewById(R.id.et_pwd);
button = (Button) findViewById(R.id.btn_login);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String name = etName.getText().toString();
String password = etPassword.getText().toString();
if(name.equals("Errol_King") && password.equals("123456")){
Toast.makeText(MainActivity.this,"登录成功", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this,"登录失败", Toast.LENGTH_SHORT).show();
}
}
});
}
}
布局activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入姓名" />
<EditText
android:id="@+id/et_pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入密码" />
<Button
android:id="@+id/btn_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录"/>
</LinearLayout>
修改AndroidManifest中的启动页为MainActivity
<activity android:name=".MainActivity" android:label="@string/title_notes_list">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
当输入用户名Errol_King
和密码123456
后提示“登录成功”。当输入其他提示“登录失败”
现在来写测试代码,让程序自动输入用户名Errol_King
和密码1234567
,因为密码错误,所以会提示“登录失败”,如果页面上如期出现“登录失败”则测试通过
在以下目录下新建LoginTest文件
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190903090417534.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTAzNTY3Njg=,size_16,color_FFFFFF,t_70)
@RunWith(AndroidJUnit4.class)
public class LoginTest {
@Rule
public ActivityTestRule<MainActivity> activityTestRule =
new ActivityTestRule<>(MainActivity.class);
private Solo solo;
//在执行我们的测试方法之前调用
@Before
public void setUp() throws Exception {
//setUp() is run before a test case is started.
//This is where the solo object is created.
solo = new Solo(InstrumentationRegistry.getInstrumentation(),
activityTestRule.getActivity());
}
//我们写的测试方法
@Test
public void testLogin(){
solo.waitForText("登录");
EditText name = (EditText) solo.getView(R.id.et_name);
EditText pwd = (EditText) solo.getView(R.id.et_pwd);
Button button = (Button) solo.getView(R.id.btn_login);
//在用户名和密码输入框输入文字
solo.enterText(name, "Errol_King");
solo.enterText(pwd, "1234567");
//点击登录按钮
solo.clickOnView(button);
boolean isSuccess = solo.searchText("登录失败");
//boolean isSuccess = solo.searchText("Errol_King");
//第一个参数:验证失败情况下,要显示的提示字符
//第二个参数:要用来断言的表达式
assertTrue("错误提示没有出现",isSuccess);
}
//我们写的测试方法执行完之后
@After
public void tearDown() throws Exception {
//关闭打开的activity
solo.finishOpenedActivities();
}
}
右键,run
![在这里插入图片描述](https://img-blog.csdnimg.cn/2019090309051163.png)
程序会在手机上自动运行
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190903090719574.gif)
运行结束后,AS会提示测试通过
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190903090802368.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTAzNTY3Njg=,size_16,color_FFFFFF,t_70)
如果我们修改LoginTest中代码
boolean isSuccess = solo.searchText("用户名或密码错误");
因为页面上提示的是“登录失败”而非“用户名或密码错误”,所以测试会失败,AS也会提示失败原因
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190903091327721.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTAzNTY3Njg=,size_16,color_FFFFFF,t_70)
测试2
修改MainActivity中程序,登录成功后跳转UserActivity
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String name = etName.getText().toString();
String password = etPassword.getText().toString();
if(name.equals("") && password.equals("")){
Toast.makeText(MainActivity.this,"用户名和密码不能为空", Toast.LENGTH_SHORT).show();
}else{
if(name.equals("Errol_King") && password.equals("123456")){
Toast.makeText(MainActivity.this,"登录成功", Toast.LENGTH_SHORT).show();
startActivity(new Intent(MainActivity.this,UserActivity.class));
}else {
Toast.makeText(MainActivity.this,"登录失败", Toast.LENGTH_SHORT).show();
}
}
}
});
其中UserActivity中有一个添加按钮
新建LoginTest2,其余代码不变,修改testLogin()方法
@Test
public void testLogin(){
solo.waitForText("登录");
EditText name = (EditText) solo.getView(R.id.et_name);
EditText pwd = (EditText) solo.getView(R.id.et_pwd);
Button button = (Button) solo.getView(R.id.btn_login);
//在用户名和密码输入框输入文字
solo.enterText(name, "Errol_King");
solo.enterText(pwd, "123456");
//点击登录按钮
solo.clickOnView(button);
//判断有没有显示UserActivity
solo.assertCurrentActivity("程序没有跳转",UserActivity.class);
//判断页面上有没有显示添加按钮
View view = solo.getView(R.id.btn_add);
boolean isSuccess = view.isShown();
assertTrue("没显示添加按钮",isSuccess);
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190903094821923.gif)
AS显示测试通过
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190903094854283.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTAzNTY3Njg=,size_16,color_FFFFFF,t_70)
测试3
我们修改UserActivity的代码,点击添加按钮,显示一个EditText和一个保存Button,单击保存按钮,如果输入内容为空,则提示“消息不能为空“,否则提示”留言成功“,并且动态添加View
public class UserActivity extends Activity {
private Button btn_add;
private Button btn_save;
private EditText et_message;
private View ll_container;
private LinearLayout ll_list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user);
btn_add = (Button) findViewById(R.id.btn_add);
btn_save = (Button) findViewById(R.id.btn_save);
et_message = (EditText) findViewById(R.id.et_message);
ll_container = findViewById(R.id.ll_container);
ll_list = (LinearLayout)findViewById(R.id.ll_list);
btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ll_container.setVisibility(View.VISIBLE);
}
});
btn_save.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String message = et_message.getText().toString();
if(message.equals("")){
Toast.makeText(UserActivity.this,"消息不能为空",Toast.LENGTH_SHORT).show();
}else {
et_message.setText("");
Toast.makeText(UserActivity.this,"留言成功",Toast.LENGTH_SHORT).show();
addView(message);
}
}
});
}
public void addView(String str) {
TextView child = new TextView(this);
child.setTextSize(20);
child.setTextColor(Color.parseColor("#ff0000"));
child.setText(str);
ll_list.addView(child);
}
}
修改LoginTest2中测试方法
//我们写的测试方法
@Test
public void testLogin(){
solo.waitForText("登录");
EditText name = (EditText) solo.getView(R.id.et_name);
EditText pwd = (EditText) solo.getView(R.id.et_pwd);
Button button = (Button) solo.getView(R.id.btn_login);
//在用户名和密码输入框输入文字
solo.enterText(name, "Errol_King");
solo.enterText(pwd, "123456");
//点击登录按钮
solo.clickOnView(button);
//判断有没有显示UserActivity
solo.assertCurrentActivity("程序没有跳转",UserActivity.class);
//判断页面上有没有显示添加按钮
View view = solo.getView(R.id.btn_add);
boolean isSuccess = view.isShown();
assertTrue("没显示添加按钮",isSuccess);
//单击添加按钮
solo.clickOnView(view);
//屏幕上有没有出现“待办事项”
isSuccess = solo.searchText("待办事项");
assertTrue(isSuccess);
//模拟用户单击保存按钮
view = solo.getView(R.id.btn_save);
solo.clickOnView(view);
isSuccess = solo.searchText("消息不能为空");
assertTrue(isSuccess);
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190903101800105.gif)
AS提示测试成功
测试4
新建LoginTest3,代码从LoginTest2中粘过来,只修改测试方法
@Test
public void testLogin(){
solo.waitForText("登录");
EditText name = (EditText) solo.getView(R.id.et_name);
EditText pwd = (EditText) solo.getView(R.id.et_pwd);
Button button = (Button) solo.getView(R.id.btn_login);
//在用户名和密码输入框输入文字
solo.enterText(name, "Errol_King");
solo.enterText(pwd, "123456");
//点击登录按钮
solo.clickOnView(button);
//判断有没有显示UserActivity
solo.assertCurrentActivity("程序没有跳转",UserActivity.class);
//判断页面上有没有显示添加按钮
View view = solo.getView(R.id.btn_add);
boolean isSuccess = view.isShown();
assertTrue("没显示添加按钮",isSuccess);
//单击添加按钮
solo.clickOnView(view);
//屏幕上有没有出现“待办事项”
isSuccess = solo.searchText("待办事项");
assertTrue(isSuccess);
//模拟输入内容(寻找页面上第一个EditText)
EditText editText = solo.getEditText(0);
solo.enterText(editText,"hello");
//模拟用户单击保存按钮(根据按钮上的文本查找)
view = solo.getButton("保存");
solo.clickOnView(view);
solo.assertCurrentActivity("当前页面不是UserActivity",UserActivity.class);
//判断才输入的内容在不在屏幕上
//"hello"要查找的文本
//1出现次数,只需出现一次
//true是否向下滚动
//true只考虑显示的,隐藏的不管
isSuccess = solo.searchText("hello",1,true,true);
assertTrue(isSuccess);
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190903110644836.gif)
测试5
我们在屏幕上增加一个关闭按钮,长按关闭按钮,关闭UserActivity
修改UserActivity
tv_finish.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
finish();
return false;
}
});
修改LoginTest3中测试方法
@Test
public void testLogin(){
......
//长按
solo.clickLongOnText("关闭");
//等2s后,判断是否MainActivity
isSuccess = solo.waitForActivity(MainActivity.class,2000);
solo.clearEditText(name);
solo.clearEditText(pwd);
assertTrue(isSuccess);
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190903114208860.gif)