To find the number of test methods in a JUnit Test

2019-06-23 16:43发布

问题:

Is there a way to know the number of test methods in a test case?

What I want to do is have a test case which tests several scenarios and for all these i would be doing the data setUp() only once. Similarly I would like to do the cleanup (tearDown()) once at the end of all the test methods.

The current approach i am using is to maintain a counter for the number of test methods that are present in the file and decrement them in the tearDown method and do the cleanup when the count reaches 0. But this counter needs to be taken care of whenever new test methods are added.

回答1:

Instead of using setup/teardown you should probably use methods annotated with @BeforeClass and @AfterClass instead.



回答2:

You can do this through @BeforeClass and @AfterClass in JUnit4: http://junit.org/apidocs/org/junit/BeforeClass.html

Volker



回答3:

Here is the piece of code I wrote to find all the test cases in my JUnit project. What it does is reads the files(under package mentioned in code) and using reflection APIs, finds the test cases with annotations "@Test" and also the ones which start with "test" but don't have the @Test annotation

public class TestCaseCount {

      private static List<Class> getClasses(String packageName)
          throws ClassNotFoundException, IOException {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        assert classLoader != null;
        String path = packageName.replace('.', '/');
        Enumeration<URL> resources = classLoader.getResources(path);
        List<File> dirs = new ArrayList<File>();
        while (resources.hasMoreElements()) {
          URL resource = resources.nextElement();
          dirs.add(new File(resource.getFile()));
        }

        ArrayList<Class> classes = new ArrayList<Class>();
        for (File directory : dirs) {
          classes.addAll(findClasses(directory, packageName));
        }
        return classes /* .toArray(new Class[classes.size()]) */;
      }

      private static List<Class> findClasses(File directory, String packageName)
          throws ClassNotFoundException {
        List<Class> classes = new ArrayList<Class>();
        if (!directory.exists()) {
          return classes;
        }

        File[] files = directory.listFiles();
        for (File file : files) {
          if (file.isDirectory()) {
            assert !file.getName().contains(".");
            classes.addAll(findClasses(file, packageName + "." + file.getName()));
          } else if (file.getName().endsWith(".class")) {
            classes.add(Class.forName(packageName + '.'
                + file.getName().substring(0, file.getName().length() - 6)));
          }
        }
        return classes;
      }

      public static void main(String args[]) {

        ArrayList<Class> classes = new ArrayList<Class>();

        try {
          // Feature1 Test Cases
          classes.addAll(TestCaseCount.getClasses("mypackage.feature1.tests"));

          // Feature2 Test Cases
          classes.addAll(TestCaseCount.getClasses("mypackage.feature2.tests1"));
          classes.addAll(TestCaseCount.getClasses("mypackage.feature2.tests2"));

          // Feature3 Test Cases
          classes.addAll(TestCaseCount.getClasses("mypackage.feature3.tests"));

        } catch (Exception e) {
          e.printStackTrace();
        }

        int testcaseCount = 0;
        for (Class cl : classes) {
          System.out.println("Test Class Name : " + cl.getName());

          Method[] methods = cl.getDeclaredMethods();

          for (Method method : methods) {
            Annotation[] annotations = method.getDeclaredAnnotations();
            if (annotations.length == 0 && method.getName().startsWith("test")) {
              testcaseCount++;
            } else {
              for (Annotation annotation : annotations) {
                if (annotation.annotationType().toString()
                    .equals("interface org.junit.Test")) {
                  testcaseCount++;
                }
              }
            }
          }
        }
        System.out.println("Total Test Cases " + testcaseCount);
      }
    }


回答4:

Short example for counting tests with @BeforeClass, @AfterClass and @Before.

public class CountTest {
  static int count;

  @BeforeClass
  public static void beforeClass() {
    count = 0;
  }

  @Before
  public void countUp() {
    count++;
  }

  @AfterClass
  public static void printCount() {
    System.out.println(count + " tests.");
  }

  @Test
  public void test1() {
    assertTrue(true);
  }
  // some more tests

Output will be, e.g.:

5 tests.



回答5:

If you are using Junit4 and the suggestion given by others is the correct one. But if you using earlier version then use this technique to achieve what you want -

You can define a suite for all those tests for which you want to setup and teardown only once. Take a look at junit.extensions.TestSetup class. Instead of executing your test classes you need to then execute these suites.



回答6:

A solution for junit 3 is to call a special setup method in every test which checks a static flag. if the flag is not set, run the global setup. If it is, skip the setup.

Make sure the global setup is properly synchronized if you want to run tests in parallel.



回答7:

Using @Rules on TestWatcher you can take note of count and many other things like method name etc. You can override these methods and use .

@Override   
public Statement apply(Statement base, Description description){
    return super.apply(base, description);  
}

@Override   
protected void failed(Throwable e, Description description) {
    failed.add(description);
    LogUtil.error("[FAILED] "+description.getMethodName()+" [Test Failed]"+e.getMessage());
    super.failed(e, description);
}

@Override   
protected void finished(Description description) {      
    LogUtil.info("[FINISHED] "+description.getMethodName());
    super.finished(description);
}

@Override    
protected void skipped(AssumptionViolatedException e,Description description) {
    LogUtil.error("[FAILED] Test Failed due to Assumption Voilation "+e.getMessage());
    super.skipped(e,description);
}

@Override
protected void starting(Description description) {
    LogUtil.info("-----------------------------------------------------------");
    LogUtil.info("[STARTED]  "+description.getMethodName());
    super.starting(description);
}

@Override
protected void succeeded(Description description) { 
    passed.add(description);
    LogUtil.info("[PASSED] "+description.getMethodName());
    super.succeeded(description);
}

In your Junit Testcase Use

@Rule
public TestRule watcher = new TestWatcherChild();


标签: java junit