Android jUnit TestCase:何时真正调用 Activity onCreate()?
我对测试相当陌生,正在尝试探索 jUnit Tests 和 Robotium
。我的应用程序有 4 个屏幕。
Splash Screen --> Screen2--> Screen 3--> Autocomplete Screen.
[init()] [ check values generated by init() method]
自动完成屏幕是用户输入内容的地方,应用程序从大型产品数据库中执行自动完成。在启动屏幕中,我使用另一个类中的 init()
方法初始化许多应用程序变量。这个 init()
方法将加载用户首选项,检查数据库创建等...(产品数据库预先打包在 apk 中,我在第一次启动时复制数据库并将其标记为 <代码>SharedPreferences作为复制= true)。
问题:如何隔离自动完成屏幕的测试? AutocompleteActivity 的 onCreate 依赖于 SplashScreen 中调用的 init() 。我不确定 jUnit 何时创建 Activity 的实例(可能在构造函数中?)。这是我的测试用例代码:
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
import android.widget.ListView;
import com.jayway.android.robotium.solo.Solo;
import com.supervalu.mobile.android.AutoCompleteActivity;
import com.supervalu.mobile.android.db.LocalDb;
public class AutocompleteTest extends
ActivityInstrumentationTestCase2<AutoCompleteActivity> {
private Solo solo;
public AutocompleteTest() {
super("com.****.*****.*****", AutoCompleteActivity.class);
}
protected void setUp() throws Exception {
super.setUp();
LocalDb.init(getActivity().getApplicationContext());
solo = new Solo(getInstrumentation(), getActivity());
}
public void test1Character() {
solo.sleep(2000);
solo.enterText(0, "c");
solo.sleep(10000);
View v = getActivity().findViewById(
com.*****.****.*****.R.id.list);
solo.waitForView(v);
assertTrue(((ListView) v).getChildCount() > 0);
}
public void test3Character() {
LocalDb.init(getActivity().getApplicationContext());
solo.enterText(0, "che");
View v = getActivity().findViewById(
com.*****.****.*****.R.id.list);
solo.waitForView(v);
assertTrue(((ListView) v).getChildCount() > 0);
}
protected void tearDown() throws Exception {
solo.finishOpenedActivities();
super.tearDown();
}
测试用例不断崩溃,因为 onCreate 需要来自 LocalDb
的一些值,而这些值必须由 init()
方法初始化。
我无法在构造函数中的 super 调用之前添加 init() 函数。有没有解决这个问题的方法,或者我是否需要从启动屏幕启动测试用例?
问题 2:如果我从启动屏幕开始测试,我必须首先导航到自动完成屏幕,然后才能对其执行任何测试。假设我也这样做了,那么对于每个测试:test1character(),该类执行setUp(),然后执行测试,然后tearDown(),然后它重新启动test3characters()函数的整个序列。在实际测试输入之前,每次都重复导航到自动完成屏幕是非常痛苦的。对此还有什么建议吗?
我不知道该采取什么方法。有人可以指导我吗?
I am fairly new to testing and am trying to explore jUnit Tests and Robotium
. My application has 4 screens.
Splash Screen --> Screen2--> Screen 3--> Autocomplete Screen.
[init()] [ check values generated by init() method]
Autocomplete screen is where the user types something, and the app performs autocomplete from a large database of Products. In the splash screen I am initializing many app variables using an init()
method in another class. This init()
method will load usedr preferences, check for database creation etc...(The product database comes pre-packaged in the apk and i am copying the database on first launch and mark it in SharedPreferences
as copied=true).
Problem : How do i isolate the testing of Autocomplete Screen ? The onCreate of AutocompleteActivity depends on init() having been called in the SplashScreen. I am not sure when the jUnit creates an instance of the Activity
, (probably in the constructor? ). Here is my TestCaseCode:
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
import android.widget.ListView;
import com.jayway.android.robotium.solo.Solo;
import com.supervalu.mobile.android.AutoCompleteActivity;
import com.supervalu.mobile.android.db.LocalDb;
public class AutocompleteTest extends
ActivityInstrumentationTestCase2<AutoCompleteActivity> {
private Solo solo;
public AutocompleteTest() {
super("com.****.*****.*****", AutoCompleteActivity.class);
}
protected void setUp() throws Exception {
super.setUp();
LocalDb.init(getActivity().getApplicationContext());
solo = new Solo(getInstrumentation(), getActivity());
}
public void test1Character() {
solo.sleep(2000);
solo.enterText(0, "c");
solo.sleep(10000);
View v = getActivity().findViewById(
com.*****.****.*****.R.id.list);
solo.waitForView(v);
assertTrue(((ListView) v).getChildCount() > 0);
}
public void test3Character() {
LocalDb.init(getActivity().getApplicationContext());
solo.enterText(0, "che");
View v = getActivity().findViewById(
com.*****.****.*****.R.id.list);
solo.waitForView(v);
assertTrue(((ListView) v).getChildCount() > 0);
}
protected void tearDown() throws Exception {
solo.finishOpenedActivities();
super.tearDown();
}
The test case keeps creashing because the onCreate requires some values from the LocalDb
whcih had to be initialiazed by init()
method.
I cannot add the init() function before the super call in the constructor. Is there any work around for this , or do i need to start the test case from the splash screen ?
Problem 2 : If i start testing from splash scree, I have to first navigate to the autocmplete screen before being able to perform any tests on it. Suppose i did that as well, then for each test: test1character() the class executes setUp() and then the test and then tearDown(), then it restarts whole sequence for test3characters() function. It gets very painful to keep repeating navigating to autocompltete screen every time before actually testing inputs. Any suggestions on this as well ?
I am not sure what approach to take. Can someone please guide me?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我有类似的问题并且能够解决它。
在 setUp() 方法中调用 getActivity() 是没有用的。它不会影响您的测试方法。
您必须使用:
例如使用
而不是
希望这对您有用!
干杯安东尼诺
I had a similar problem and was able to fix it.
In your setUp() method it is no use to call getActivity(). It doesn't affect your test methods.
You have to use:
for example use
instead of
Hope this works for you!
Cheers Antonino
我发现模拟框架是执行独立方法测试的更好选择
Android 活动方法。目前,jMockit 是唯一能够有效模拟 endroid 基类的框架。
您将能够丢弃大量设置和拆卸代码。请参阅测试用例:
https ://github.com/ko5tik/andject/blob/master/src/test/java/de/pribluda/android/andject/ViewInjectionTest.java
I found mocking frameworks to be better alternative to perform isolated method tests of
android activities methods. At the moment jMockit is only framework capable to mock up endroid base classes effectively.
You will be able to discard a lot of setup and teardown code. See test case:
https://github.com/ko5tik/andject/blob/master/src/test/java/de/pribluda/android/andject/ViewInjectionTest.java
我不太明白你的问题,但我会尽力提供帮助。
执行 Activity 启动(并调用其 onCreate 回调)的方法是:
通常的位置是在
setUp()
方法中(在每次测试之前调用)。正如您所说,对于每个测试,都会调用
setUp()
和tearDown()
方法。我认为测试应用程序导航的最佳方法是进行简单的测试,并根据需要创建所有意图,以便启动需要测试的所有活动。
我希望它有帮助。
I'm not really understand your problem, but I will try to help.
To perform the Activity start (and calls to the onCreate callback of it) is with:
A usual place for it is in the
setUp()
method (to call before each test).As you say for each test the
setUp()
andtearDown()
methods are called.I think that the best way to test your app navigation is in a simple test, and create all intents as you need to can start all the Activities nedded to test.
I hope it helps.
如果您进行单元测试,您应该将测试类扩展为 ActivityUnitTestCase 来测试单个活动,并使用 startActivity 方法来调用 onCreate。 ActivityInstrumentationTestCase2 用于对活动进行功能测试。
从 android 参考文档中查看更多内容...
启动被测试的活动,就像它是由 Context.startActivity() 启动一样,提供它提供的参数。当您使用此方法启动活动时,它将自动被tearDown()停止。
此方法将调用 onCreate(),但如果您希望进一步练习 Activity 生命周期方法,您必须从测试用例中亲自调用它们。
不要从 setUp() 方法中调用。您必须从每个测试方法中调用此方法。
If your doing unit testing , You should extend your test class to ActivityUnitTestCase to test a single activity and use startActivity method which will call your onCreate. ActivityInstrumentationTestCase2 is for functional testing the activity.
see more from the android reference doc...
Start the activity under test, in the same way as if it was started by Context.startActivity(), providing the arguments it supplied. When you use this method to start the activity, it will automatically be stopped by tearDown().
This method will call onCreate(), but if you wish to further exercise Activity life cycle methods, you must call them yourself from your test case.
Do not call from your setUp() method. You must call this method from each of your test methods.