从JUnit命令行获取测试列表 [英] Getting list of tests from JUnit command line

查看:85
本文介绍了从JUnit命令行获取测试列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简而言之,我的问题是我想从命令行运行一些JUnit测试,并且希望能够看到:

My problem, in short, is that I want to run some JUnit tests from a command line and I would like to be able to see:

  • 所有测试的列表(无论是否运行).
  • 所有通过的测试的列表.
  • 所有失败的测试列表

第一个项目符号的原因是因为我相信,如果一个测试调用System.exit,其他测试不会运行,我仍然想知道这些测试,即使它们没有运行.

The reason for the first bullet, is because I believe if one test calls System.exit, the others won't run, I still want to know about these tests, even if they didn't run.

让我们说我有这个测试班:

Lets say I have this test class:

    import junit.framework.TestCase;
    public class ALoadOfTests extends TestCase {

    public void testFoo() {
        int a = 5;
        int b = 10;
        int result = a + b;
        assertEquals(15, result);
    }

    public void testBar() {
        fail();
    }

    public void testBaz() {
        fail();
    }       
}

如果我使用以下命令运行它:

If I run this using the commands:

javac -cp ".;C:\Users\username\Desktop\Test\junit-4.11.jar;C:\Users\username\Desktop\Test\hamcrest-core-1.3.jar" ALoadOfTests.java
java -cp ".;C:\Users\username\Desktop\Test\junit-4.11.jar;C:\Users\username\Desktop\Test\hamcrest-core-1.3.jar" junit.textui.TestRunner ALoadOfTsts

输出为:

.F.F.
Time: 0.002
There were 2 failures:
1) testBar(ALoadOfTests)junit.framework.AssertionFailedError
        at ALoadOfTests.testBar(ALoadOfTests.java:12)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
2) testBaz(ALoadOfTests)junit.framework.AssertionFailedError
        at ALoadOfTests.testBaz(ALoadOfTests.java:16)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

FAILURES!!!
Tests run: 3,  Failures: 2,  Errors: 0

这里的问题是输出不会告诉我存在并通过的testFoo的名称. 此外,如果我将其中之一更改为使用System.exit,那么我们根本不会获得太多输出,我们只会得到:

The problem here is that the output doesn't tell me the name of testFoo which exists and passed. Furthermore, if I change one of them to use System.exit, then we don't get much output at all, we just get:

.F.F.

理想情况下,为了能够获取我需要的所有信息,如果我可以先打印出测试名称列表,然后再运行任何测试(以及任何可能的System.exit),那么我就可以看到通过了哪些测试,哪些通过了测试失败(或没有运行).

Ideally, to be able to get all the information I need, if I could print out a list of test names first, before any tests are ran (and any chance of System.exit) then I can see which passed and which failed (or didn't run).

如果我得到的输出看起来类似于:

If I could get output that just looks similar to:

Tests:
testFoo
TestBar
TestBaz
Results:
TestFoo(passed)
TestBar(failed:reason)

那我可以放心地假设:

TestFoo passed
TestBar failed
TestBaz never ran, probably because some test called system.exit.

使用自定义跑步者可以吗?如果是这样,将不胜感激从何处开始的任何提示.

Is this possible using a custom runner? If it is, any hints on where to start would be greatly appreciated.

不幸的是,我无法控制代码,应该假设它在每种方法中都可能包含System.exit.我对测试也几乎没有控制权,因此在设置方法中打印出测试名称并不理想.

Unfortunately I have no control over the code, it should be assumed that it may contain System.exit, possibly, in every method. I also have little control over the tests, so printing out the test names in the setup method isn't ideal.

谢谢

推荐答案

更改JUnit输出

博客中所述a>您可以编写自己的测试监听器,并在测试通过或失败时打印出自己的消息.

As described in this blog you can write your own test listener and print out your own messages for when tests pass or fail.

public class ExecutionListener extends RunListener
{
... //feel free to override other methods too

/**
 *  Called when an atomic test has finished, whether the test succeeds or fails.
 * */
public void testFinished(Description description) throws java.lang.Exception
{
    System.out.println("Finished execution of test case : "+ description.getMethodName());
}

/**
 *  Called when an atomic test fails.
 * */
public void testFailure(Failure failure) throws java.lang.Exception
{
    System.out.println("Execution of test case failed : "+ failure.getMessage());
}

/**
 *  Called when a test will not be run, generally because a test method is annotated with Ignore.
 * */
public void testIgnored(Description description) throws java.lang.Exception
{
    System.out.println("Execution of test case ignored : "+ description.getMethodName());
}

}

然后用一个主代码编写您自己的类以运行Junit(而不是运行junit.jar)

Then write your own class with a main to run Junit (instead of running the junit.jar)

public class ExecuteWithRunListener
{
    public static void main(String[] args)
    {
        JUnitCore runner = new JUnitCore();
        //Adding listener here
        runner.addListener(new ExecutionListener());
        runner.run(TestFeatureOne.class, TestFeatureTwo.class);
    }
} 

如何防止来自System.exit的呼叫实际退出

您的测试可以使用自己的SecurityManager来阻止对System.exit的调用执行任何操作.下面的代码将使对System.exit()的任何调用都引发一个特殊的Exception,我们可以在测试中捕获该异常,以确保我们调用了exit,并且还捕获了退出代码是什么:

Your tests can use their own SecurityManager to prevent calls to System.exit from doing anything. The code below will make any calls to System.exit() throw a special Exception which we can catch in our tests to make sure we called exit and to also capture what the exit code was:

public static final SecurityManager NON_EXITABLE_MANAGER = new SecurityManager(){

    @Override
    public void checkPermission(Permission perm) {
        //allow everything
    }
    /**
     * Throws a {@link TriedToExitException} instead of exiting.
     * <p/>
     * {@inheritDoc}
     */
    @Override
    public void checkExit(int status) {
        throw new TriedToExitException(status);
    }

};

public static final class TriedToExitException extends SecurityException{
    private static final long serialVersionUID = 1L;
    private final int exitCode;

    public TriedToExitException(int exitCode){
        this.exitCode=exitCode;
    }

    @Override
    public String getMessage() {
        return String.format("tried to System.exit(%d)",exitCode);
    }

    public int getExitCode() {
        return exitCode;
    }

}

然后在单元测试中,将我们的SecurityManager替换为我们的版本,该版本会停止调用退出的操作(并保存旧的SecurityManager,以便我们在测试后可以将其恢复)

Then in your unit tests you replace the SecurityManager with our version that stops calls to exit (and save the old SecurityManager so we can restore it after the test)

private SecurityManager previousManager=null;


@Before
protected void replaceManager() throws Throwable {
    previousManager = System.getSecurityManager();
    System.setSecurityManager(NON_EXITABLE_MANAGER);
}

@After
protected void restoreManager() {
    System.setSecurityManager(previousManager);
}

 @Test
    public void testCallToExit() throws IOException{

         try{
           //something that calls System.exit
            fail("should call exit");
         }catch(TriedToExitException e){
             //make sure we get correct exit code
             assertEquals(-1, e.getExitCode());

         }
    }

这篇关于从JUnit命令行获取测试列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆