Java Android:如何使用Robolectric运行PIT突变测试?

Java Android:如何使用Robolectric运行PIT突变测试?,java,android,eclipse,robolectric,pitest,Java,Android,Eclipse,Robolectric,Pitest,如何使用和测试Android应用程序 使用Robolectric,您可以在JVM中运行Android测试。使用PIT,您可以显示线覆盖率并进行突变测试。对我来说,使用Eclipse+插件是可以的,但没有要求 这就是我迄今为止所尝试的: 我有一个Android项目,我们称之为MyProject 现在我想使用和在JVM中测试MyProject。因此,我创建了另一个名为MyTest的项目,并成功地运行了Robolectric测试,如中所述。这是my.app.tests.MyActivityTest的

如何使用和测试Android应用程序

使用Robolectric,您可以在JVM中运行Android测试。使用PIT,您可以显示线覆盖率并进行突变测试。对我来说,使用Eclipse+插件是可以的,但没有要求


这就是我迄今为止所尝试的:

我有一个Android项目,我们称之为MyProject

现在我想使用和在JVM中测试MyProject。因此,我创建了另一个名为MyTest的项目,并成功地运行了Robolectric测试,如中所述。这是
my.app.tests.MyActivityTest
的外观:

@RunWith(RobolectricTestRunner.class)
public class MyActivityTest {
    @Test
    public void myTest() throws Exception {
        String appName = new MainActivity().getResources().getString(R.string.app_name);
        Assert.assertEquals(appName, "MyProject");
    }
}
现在是棘手的部分:我想在我的机器人分子测试中增加PIT的线覆盖率和突变测试。第一次尝试使用-没有运气。Pitclipse似乎还不支持Eclipse项目依赖性

因此,我的第二次尝试是使用命令行,如中所述:

首先,我确保使用Junit从命令行成功运行测试:

java -cp <classpath> org.junit.runner.JUnitCore my.app.tests.MyActivityTest
然而,这导致了我在下面发布的异常。我想我需要使用PIT的
--excludedclass
参数排除一些类,但是没有关于哪个类可能导致问题的提示。请注意,
MyActivityTest
没有超类和显式构造函数

java.lang.NullPointerException
ERROR Description [testClass=my.app.tests.MyActivityTest, name=myTest(my.app.tests.MyActivityTest)] -> java.lang.NullPointerException
    at org.pitest.boot.CodeCoverageStore.visitProbes(CodeCoverageStore.java:92)
    at my.app.tests.MyActivityTest.<init>(MyActivityTest.java:22)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:532)
    at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:195)
    at org.robolectric.RobolectricTestRunner$HelperTestRunner.createTest(RobolectricTestRunner.java:647)
    at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:244)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:241)
    at org.robolectric.RobolectricTestRunner$HelperTestRunner.methodBlock(RobolectricTestRunner.java:657)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:227)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:175)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.pitest.junit.adapter.CustomRunnerExecutor.run(CustomRunnerExecutor.java:42)
    at org.pitest.junit.adapter.AdaptedJUnitTestUnit.execute(AdaptedJUnitTestUnit.java:86)
    at org.pitest.coverage.execute.CoverageDecorator.execute(CoverageDecorator.java:50)
    at org.pitest.containers.UnContainer.submit(UnContainer.java:46)
    at org.pitest.Pitest$3.run(Pitest.java:148)
    at java.lang.Thread.run(Thread.java:679)
java.lang.NullPointerException
错误描述[testClass=my.app.tests.MyActivityTest,name=myTest(my.app.tests.MyActivityTest)]->java.lang.NullPointerException
位于org.pitest.boot.CodeCoverageStore.visitProbes(CodeCoverageStore.java:92)
在my.app.tests.MyActivityTest.(MyActivityTest.java:22)
位于sun.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法)
位于sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
在sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
位于java.lang.reflect.Constructor.newInstance(Constructor.java:532)
位于org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:195)
位于org.roblectric.roblectricttestrunner$HelperTestRunner.createTest(roblectricttestrunner.java:647)
位于org.junit.runners.BlockJUnit4ClassRunner$1.runReflectCall(BlockJUnit4ClassRunner.java:244)
位于org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
位于org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:241)
位于org.roblectric.roblectricttestrunner$HelperTestRunner.methodBlock(roblectricttestrunner.java:657)
位于org.roblectric.roblectrictTestRunner$2.evaluate(roblectrictTestRunner.java:227)
位于org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
位于org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
位于org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
位于org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
位于org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
位于org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
访问org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
位于org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
位于org.roblectric.roblectrictTestRunner$1.evaluate(roblectrictTestRunner.java:175)
位于org.junit.runners.ParentRunner.run(ParentRunner.java:309)
位于org.pitest.junit.adapter.CustomRunnerExecutor.run(CustomRunnerExecutor.java:42)
在org.pitest.junit.adapter.adaptedJunitestUnit.execute(adaptedJunitestUnit.java:86)
位于org.pitest.coverage.execute.CoverageDecorator.execute(CoverageDecorator.java:50)
位于org.pitest.containers.UnContainer.submit(UnContainer.java:46)
在org.pitest.pitest$3.run(pitest.java:148)
运行(Thread.java:679)

看起来正在发生的事情是正在加载pit的代码覆盖率存储类的两个副本。这是一个针对每个测试跟踪每个类的行覆盖率的类

测试中的类由一个整数id标识,该id在加载时分配给它们-该id嵌入到字节码操作添加的探测调用中,字节码操作调用代码覆盖存储类

代码假定存储中每个类id都有一个可用的条目,因为每个id在加载时都在存储中注册。这一假设被打破,因为接收探测调用的类的版本与最初注册类的版本不同

要说pit 0.31及以下与Roboelectric不兼容,还有很长的路要走

我需要看一看RoboeElectric在幕后到底做了些什么,看看这是否可以在未来的版本中修复

----更新---


0.32-SNAPSHOT版本似乎与Roboelectric兼容(见注释)。

我首先使用maven插件-这是核心PIT代码库的一部分。eclipse插件是第三方的,不太成熟。我对Android开发或Roboelectric不太熟悉,但从谷歌上看,只要普通的jvm字节码被写到磁盘上,它就应该与PIT一起工作。如果您成功(或失败),请发布到pit google用户组。@henry在第二次尝试中,我尝试从命令行使用pit。普通JUnit测试(不使用robolectric)可以很好地使用PIT。但是,使用robolectric的MyActivityTest会产生上面发布的异常。你知道问题出在哪里吗?我没有PIT方面的经验。它是如何进行变异的?Robolectric拥有自己的类加载器,并在飞行中执行字节码操作。这就是为什么目前还不清楚如何将它与PowerMock等库一起使用的原因。我知道,使PIT与Robolectric兼容可能是一件困难的事情。然而,PIT和Robolectric都将受益匪浅