PITest 跳过 ant

问题描述

我遇到了问题,PITest 跳过了我的一些测试。它没有报告测试类的行覆盖率和保持存活的所有突变:

将返回值替换为 Collections.emptyList for ... → NO_COVERAGE

以下列表为空:

检查的测试

我确实检查了以下内容

  • class 和 test 的类文件支持在 classpath 中的目录之一
  • 不排除测试
  • 运行同一目录中的测试
  • 正确提供了源目录
  • 即使在使用 verbose=true 进行日志记录时,控制台也不会发生错误
  • 我记录并检查了所有参数
<pitest
                pitClasspath="pit.path"
                classpath="mutation.path"
                targetClasses="my.package1.*,my.package2.*,my.package3.*"
                targetTests="my.package1.Class1Test,my.package2.sub.Class2Test,my.package3.sub.Class3Test"
                reportDir="pitest"
                sourceDir="src,testsrc"
                timestampedReports="false"
                outputFormats="HTML,XML"
                excludedClasses="my.package1.*Test,my.package2.*Test,my.package3.*Test"
                verbose="true"
        />

我使用的是 PITest 1.4.11 版,但我也使用 1.6.2 和 1.4.3 进行了测试。另外我使用的是 Java 1.8.0_211 和 ant 1.9.13。

我在以下位置建立了一个测试项目: https://github.com/johannesn/pittestskippingtests

这是这个示例项目的日志输出

Buildfile: .../pitestskipingtests/build.xml

mutationCoverage:
   [delete] Deleting directory .../pitestskipingtests/classes
   [delete] Deleting directory .../pitestskipingtests/testclasses
    [mkdir] Created dir: .../pitestskipingtests/classes
    [mkdir] Created dir: .../pitestskipingtests/testclasses
    [javac] .../pitestskipingtests/build.xml:30: warning: 'includeantruntime' was not set,defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 3 source files to .../pitestskipingtests/classes
    [javac] .../pitestskipingtests/build.xml:31: warning: 'includeantruntime' was not set,defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 3 source files to .../pitestskipingtests/testclasses
   [pitest] 19:24:08 PIT >> INFO : ---------------------------------------------------------------------------
   [pitest] 19:24:08 PIT >> INFO : Enabled (+) and disabled (-) features.
   [pitest] 19:24:08 PIT >> INFO : -----------------------------------------
   [pitest] 19:24:08 PIT >> INFO : +FFBLOCK        Filters mutations in code duplicated by finally block inlining
   [pitest] 19:24:08 PIT >> INFO : +FSTATI         Filters mutations in static initializers and code called only from them
   [pitest] 19:24:08 PIT >> INFO : +FSEQUIVEQUALS  Filters equivalent mutations that affect only performance in short cutting equals methods
   [pitest] 19:24:08 PIT >> INFO : +FFEACH         Filters mutations in compiler generated code that implements for each loops
   [pitest] 19:24:08 PIT >> INFO : +FINFINC        Filters mutations to increments that may cause infinite loops
   [pitest] 19:24:08 PIT >> INFO : +FFLOOP         Filters any mutations to increments in for loops as they may cause timeouts
   [pitest] 19:24:08 PIT >> INFO : +FRETEQUIV      Filters return vals mutants with bytecode equivalent to the unmutated class
   [pitest] 19:24:08 PIT >> INFO : +FINULL         Filters mutations in compiler generated code that checks for null by calling getClass
   [pitest] 19:24:08 PIT >> INFO : +FTRYWR         Filters mutations in code generated for try with resources statements
   [pitest] 19:24:08 PIT >> INFO : +FKOTLIN        Filters out junk mutations in bytecode created by compiler for kotlin language features
   [pitest] 19:24:08 PIT >> INFO : +FSTAtiniT      Filters mutations in static initializers and code called only from them
   [pitest] 19:24:08 PIT >> INFO : +FLOGCALL       Filters mutations in code that makes calls to logging frameworks
   [pitest] 19:24:08 PIT >> INFO : +FINFIT         Filters mutations that may cause infinite loops by removing calls to iterator.next
   [pitest] 19:24:08 PIT >> INFO : +FANN           Filters mutations in classes and methods with matching annotations of class or runtime retention
   [pitest] 19:24:08 PIT >> INFO :   [annotation]    Annotation to avoid (full package name not required)
   [pitest] 19:24:08 PIT >> INFO : -CLASSLIMIT     Limits the maximum number of mutations per class
   [pitest] 19:24:08 PIT >> INFO :   [limit]         Integer value for maximum mutations to create per class
   [pitest] 19:24:08 PIT >> INFO : -EXPORT         Exports mutants bytecode and other details to disk
   [pitest] 19:24:08 PIT >> INFO : ---------------------------------------------------------------------------
   [pitest] 19:24:08 PIT >> FINE : Running report with ReportOptions [targetClasses=[my.package1.*,my.package3.*],excludedMethods=[],excludedClasses=[my.package1.*Test,my.package3.*Test],excludedTestClasses=[],codePaths=[],reportDir=pitest,historyInputLocation=null,historyOutputLocation=null,sourceDirs=[src,testsrc],classpathelements=[.../pitestskipingtests/resources/pitest/pitest-1.4.3.jar,.../pitestskipingtests/testclasses,.../pitestskipingtests/classes,.../pitestskipingtests/lib/junit-4.12.jar],mutators=[],features=[],dependencyAnalysisMaxdistance=-1,jvmArgs=[],numberOfThreads=1,timeoutFactor=1.25,timeoutConstant=4000,targetTests=[^my\.package1\.Class1Test$,^my\.package2\.sub\.Class2Test$,^my\.package3\.sub\.Class3Test$],loggingClasses=[],maxMutationsPerClass=0,verbose=true,failWhenNoMutations=true,outputs=[HTML,XML],groupConfig=TestGroupConfig [excludedGroups=[],includedGroups=[]],fullMutationMatrix=false,mutationUnitSize=0,shouldCreateTimestampedReports=false,detectInlinedCode=false,exportLineCoverage=false,mutationThreshold=0,coverageThreshold=0,mutationEngine=gregor,javaExecutable=null,includeLaunchClasspath=false,properties={},maxSurvivors=-1,excludedRunners=[],includedTestMethods=[],testPlugin=junit,useClasspathJar=false]
   [pitest] 19:24:08 PIT >> FINE : System class path is .../pitestskipingtests/resources/pitest/pitest-1.4.3.jar:.../pitestskipingtests/resources/pitest/pitest-ant-1.4.3.jar:.../pitestskipingtests/resources/pitest/pitest-entry-1.4.3.jar:.../pitestskipingtests/resources/pitest/xmlpull-1.1.3.1.jar:.../pitestskipingtests/resources/pitest/xstream-1.4.11.1.jar:.../pitestskipingtests/lib/junit-4.12.jar
   [pitest] 19:24:08 PIT >> FINE : Maximum available memory is 3641 mb
   [pitest] 19:24:08 PIT >> FINE : MINION : Installing PIT agent
   [pitest] 
   [pitest] 19:24:09 PIT >> INFO : Sending 3 test classes to minion
   [pitest] 19:24:09 PIT >> INFO : Sent tests to minion
   [pitest] 19:24:09 PIT >> FINE : Coverage generator Minion exited ok
   [pitest] 19:24:09 PIT >> INFO : Calculated coverage in 0 seconds.
   [pitest] 19:24:09 PIT >> FINE : Used memory after coverage calculation 14 mb
   [pitest] 19:24:09 PIT >> FINE : Free Memory after coverage calculation 231 mb
   [pitest] 19:24:09 PIT >> FINE : According to coverage no tests hit the mutation MutationDetails [id=MutationIdentifier [location=Location [clazz=my.package1.Class1,method=method1,methodDesc=()Ljava/lang/String;],indexes=[4],mutator=org.pitest.mutationtest.engine.gregor.mutators.ReturnValsMutator],filename=Class1.java,block=1,lineNumber=5,description=mutated return of Object value for my/package1/Class1::method1 to ( if (x != null) null else throw new RuntimeException ),testsInorder=[],isInFinallyBlock=false,poison=norMAL]
   [pitest] 19:24:09 PIT >> FINE : According to coverage no tests hit the mutation MutationDetails [id=MutationIdentifier [location=Location [clazz=my.package2.sub.Class2,filename=Class2.java,description=mutated return of Object value for my/package2/sub/Class2::method1 to ( if (x != null) null else throw new RuntimeException ),poison=norMAL]
   [pitest] 19:24:09 PIT >> FINE : According to coverage no tests hit the mutation MutationDetails [id=MutationIdentifier [location=Location [clazz=my.package3.sub.Class3,filename=Class3.java,lineNumber=6,description=mutated return of Object value for my/package3/sub/Class3::method1 to ( if (x != null) null else throw new RuntimeException ),poison=norMAL]
   [pitest] 19:24:09 PIT >> INFO : Created  3 mutation test units
   [pitest] 19:24:09 PIT >> FINE : Used memory before analysis start 23 mb
   [pitest] 19:24:09 PIT >> FINE : Free Memory before analysis start 222 mb
   [pitest] 19:24:09 PIT >> FINE : Running 3 units
   [pitest] ================================================================================
   [pitest] - Mutators
   [pitest] ================================================================================
   [pitest] > org.pitest.mutationtest.engine.gregor.mutators.ReturnValsMutator
   [pitest] >> Generated 3 Killed 0 (0%)
   [pitest] > KILLED 0 SURVIVED 0 TIMED_OUT 0 NON_VIABLE 0 
   [pitest] > MEMORY_ERROR 0 NOT_STARTED 0 STARTED 0 RUN_ERROR 0 
   [pitest] > NO_COVERAGE 3 
   [pitest] --------------------------------------------------------------------------------
   [pitest] ================================================================================
   [pitest] - Timings
   [pitest] ================================================================================
   [pitest] > scan classpath : < 1 second
   [pitest] > coverage and dependency analysis : < 1 second
   [pitest] > build mutation tests : < 1 second
   [pitest] > run mutation analysis : < 1 second
   [pitest] --------------------------------------------------------------------------------
   [pitest] > Total  : < 1 second
   [pitest] --------------------------------------------------------------------------------
   [pitest] ================================================================================
   [pitest] - Statistics
   [pitest] ================================================================================
   [pitest] >> Generated 3 mutations Killed 0 (0%)
   [pitest] >> Ran 0 tests (0 tests per mutation)
   [pitest] 19:24:09 PIT >> INFO : Completed in 0 seconds

BUILD SUCCESSFUL
Total time: 1 second

解决方法

经过大量调试和尝试后,我发现没有找到测试方法,因为缺少 junit 依赖项 hamcrest-core。

对于遇到此类问题的其他人,请尝试调试以下方法:

org.pitest.junit.RunnerSuiteFinder#apply

根据您的测试设置(例如,如果您使用 junit),它可能是

的不同子类
org.pitest.testapi.TestSuiteFinder

我遇到了以下异常:

java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing
at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:70)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:37)
    at org.pitest.junit.adapter.AdaptedJUnitTestUnit.createRunner(AdaptedJUnitTestUnit.java:107)
    at org.pitest.junit.RunnerSuiteFinder.apply(RunnerSuiteFinder.java:40)
    at org.pitest.junit.RunnerSuiteFinder.apply(RunnerSuiteFinder.java:35)
    at org.pitest.extension.common.CompoundTestSuiteFinder.apply(CompoundTestSuiteFinder.java:20)
    at org.pitest.extension.common.CompoundTestSuiteFinder.apply(CompoundTestSuiteFinder.java:9)
    at org.pitest.testapi.execute.FindTestUnits.findTestUnits(FindTestUnits.java:47)
    at org.pitest.testapi.execute.FindTestUnits.getTestUnits(FindTestUnits.java:40)
    at org.pitest.testapi.execute.FindTestUnits.findTestUnitsForAllSuppliedClasses(FindTestUnits.java:29)
    at org.pitest.coverage.execute.CoverageMinion.discoverTests(CoverageMinion.java:156)
    at org.pitest.coverage.execute.CoverageMinion.getTestsFromParent(CoverageMinion.java:137)
    at org.pitest.coverage.execute.CoverageMinion.main(CoverageMinion.java:83)
Caused by: java.lang.ClassNotFoundException: org.hamcrest.SelfDescribing
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 26 more

异常是 runner 变量的一部分。使用以下方法打印:

((ErrorReportingRunner) runner).causes.get(0).printStackTrace()