我正在尝试编写黑盒自动化测试来断言诸如“确保登陆页面在应用程序启动后 500 毫秒内出现”和“确保登录时间少于 2 秒”之类的事情。我想通过驱动真实应用的 UI 来做到这一点,以尽可能接近地模拟真实用户。
我正在使用 Robotium 5.0.1 进行黑盒 UI 测试,我希望添加一些简单的计时代码会很简单。但是,测试似乎在不同的地方间歇性地失败,即使在不发出网络请求的地方也是如此。在模拟器中本地运行多个测试时,看起来偶尔会出现约 2 秒的延迟(我们还使用 CloudBees 在云中的 Jenkins 上运行测试,尽管我还没有在那里尝试过测试)。
Robotium 是用于此类测试的正确工具吗?对于执行此类测试的最佳方法,您有什么建议吗?
这是我的测试:
public void testLogin() {
AppData.getAppData().clear();
startTimer();
launchActivity();
assertTrue(solo.waitForFragmentByTag("landingfragment", 3000));
stopTimer();
assertWasQuickerThan(500);
startTimer();
solo.clickOnButton("Log In");
assertTrue(solo.waitForFragmentByTag("loginfragment", 3000));
stopTimer();
assertWasQuickerThan(500);
solo.enterText(0, TestUtils.EXISTING_USER_EMAIL);
solo.enterText(1, TestUtils.EXISTING_USER_PASSWORD);
startTimer();
solo.clickOnButton("Next");
assertTrue(solo.waitForActivity(LaunchActivity.class, 3000));
stopTimer();
assertWasQuickerThan(2000);
}
这是 logcat(显示登陆页面在 16 毫秒内出现,但在按下登录按钮后,登录页面出现需要 2079 毫秒):
03-12 14:46:11.535 386-571/system_process I/ActivityManager﹕ START u0 {cmp=com.example/com.example.ui.LaunchActivity} from pid 1180
03-12 14:46:11.555 1180-1193/com.example D/MyApp﹕ LoginTest: Step took 16ms to complete,
03-12 14:46:12.035 1180-1180/com.example D/dalvikvm﹕ GC_FOR_ALLOC freed 1470K, 47% free 3456K/6424K, paused 96ms, total 98ms
03-12 14:46:12.045 1180-1180/com.example I/dalvikvm-heap﹕ Grow heap (frag case) to 4.842MB for 1463056-byte allocation
03-12 14:46:12.145 1180-1281/com.example D/dalvikvm﹕ GC_FOR_ALLOC freed 5K, 25% free 4880K/6424K, paused 87ms, total 102ms
03-12 14:46:12.405 386-400/system_process I/ActivityManager﹕ Displayed com.example/com.example.ui.LaunchActivity: +848ms
03-12 14:46:13.115 1180-1180/com.example I/MyApp﹕ USER: LandingFragment: Sign in pressed,
03-12 14:46:13.315 1180-1180/com.example D/dalvikvm﹕ GC_FOR_ALLOC freed 1478K, 46% free 3508K/6424K, paused 21ms, total 23ms
03-12 14:46:13.315 1180-1180/com.example I/dalvikvm-heap﹕ Grow heap (frag case) to 4.761MB for 1324816-byte allocation
03-12 14:46:13.345 1180-1180/com.example D/dalvikvm﹕ GC_FOR_ALLOC freed 3K, 26% free 4798K/6424K, paused 23ms, total 23ms
03-12 14:46:13.395 1180-1180/com.example D/dalvikvm﹕ GC_FOR_ALLOC freed <1K, 26% free 4798K/6424K, paused 31ms, total 31ms
03-12 14:46:13.405 1180-1180/com.example I/dalvikvm-heap﹕ Grow heap (frag case) to 6.153MB for 1463056-byte allocation
03-12 14:46:13.425 1180-1281/com.example D/dalvikvm﹕ GC_FOR_ALLOC freed 0K, 21% free 6227K/7856K, paused 26ms, total 26ms
03-12 14:46:13.445 1180-1180/com.example I/Choreographer﹕ Skipped 47 frames! The application may be doing too much work on its main thread.
03-12 14:46:13.635 1180-1193/com.example D/MyApp﹕ LoginTest: Step took 2079ms to complete,
03-12 14:46:14.695 1180-1180/com.example I/Choreographer﹕ Skipped 52 frames! The application may be doing too much work on its main thread.
03-12 14:46:15.325 1180-1193/com.example I/TestRunner﹕ failed: testLogin(com.example.blackbox.LoginTest)
03-12 14:46:15.335 1180-1193/com.example I/TestRunner﹕ ----- begin exception -----
03-12 14:46:15.335 1180-1193/com.example I/TestRunner﹕ junit.framework.AssertionFailedError: Step was too slow, expected 500ms but took 2079ms
at junit.framework.Assert.fail(Assert.java:50)
at junit.framework.Assert.assertTrue(Assert.java:20)
at com.example.blackbox.BaseBlackBoxTest.assertWasQuickerThan(BaseBlackBoxTest.java:57)
at com.example.blackbox.LoginTest.testLogin(LoginTest.java:52)
...这是我的测试类扩展的 BaseBlackBoxTest 类:
abstract class BaseBlackBoxTest<T extends android.app.Activity>
extends ActivityInstrumentationTestCase2<T> {
protected Solo solo;
protected long mStartTime;
protected long mStopTime;
@Before
public void setUp() throws Exception {
solo = new Solo(getInstrumentation(), getActivity());
}
@After
public void tearDown() throws Exception {
solo.finishOpenedActivities();
}
public BaseBlackBoxTest(Class clazz) {
super(clazz);
}
protected void launchActivity() {
Activity activity = getActivity();
Intent intent = new Intent(activity, activity.getClass());
activity.startActivity(intent);
solo.assertCurrentActivity("Expecting " + activity.getClass(), activity.getClass());
}
// TIMING UTILITIES //
protected void startTimer() {
mStartTime = System.nanoTime();
}
protected void stopTimer() {
mStopTime = System.nanoTime();
}
protected void assertWasQuickerThan(long maxDurationMillis) {
long durationMillis = (mStopTime - mStartTime) / 1000000;
LogIt.d(this, "Step took " + durationMillis + "ms to complete");
assertTrue("Step was too slow, expected " + maxDurationMillis + "ms but took " + durationMillis + "ms",
durationMillis < maxDurationMillis);
}
}
最佳答案
恕我直言,我认为您不应该进行此类自动化性能测试,因为您无法控制模拟器的性能。您应该专注于测试您的应用显示的内容,而不是它的运行速度。
如果您需要检查网络服务的可用性,您可以进行单独的测试,调用 HTTP 请求并在您指定的超时后失败。
关于android - Robotium 是否可以可靠地测试 Activity 和 fragment 的启动速度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22361656/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的