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.
Instead of using setup/teardown you should probably use methods annotated with @BeforeClass and @AfterClass instead.
You can do this through @BeforeClass and @AfterClass in JUnit4:
http://junit.org/apidocs/org/junit/BeforeClass.html
Volker
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);
}
}
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.
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.
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.
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();