I have a test suite that runs all test classes
#RunWith(Suite.class)
#Suite.SuiteClasses({TestClass1.class, TestClass1.class})
}
public class AllTests extends TestCase {
public AllTests(String name) {
super(name);
}
public static TestSuite suite() {
TestSuite suite = new TestSuite("com.myapp.test.AllTests");
return suite;
}
}
is it possible to implement a custom runner that will run only one method, say "onlyMethodToRun", from every class in the suite?
Yes. Suite.java implements a test runner that examines the classes listed in #Suite.SuiteClasses and uses RunnerBuilders to find every test method. You should be able to reuse a lot of JUnit's code to implement a Runner that instead only checks for a single method on every class and perhaps uses a subclass of BlockJUnit4ClassRunner that overrides computeTestMethods to only attempt a single method.
Related
I have a multi module project spring boot project, where each module produces a jar. Each module has a src/main/test with junit 5 tests. Is there a way to run code before and after all the tests in src/main/test in a specific module execute? For example if I have 2 modules A, and B I want.
run code before all tests in module A execute
run code all tests module A execute
run code before all tests in module B execute
run code after all tests in module B execute
You can make use of inheritance and the annotation #BeforeAll, optionally with a flag to execute only once for all inheriting test classes.
public class ModuleBaseClass {
private static boolean started = false;
#BeforeAll
public static void beforeAllMethod() {
if (!started) {
System.out.println("#BeforeAll static method invoked once.");
started = true;
}
System.out.println("#BeforeAll static method invoked for every class.");
}
}
public class ModuleFeature1Class extends ModuleBaseClass {
#Test
public void testMethod() {
System.out.println("ModuleFeature1Class: in testMethod().");
}
}
public class ModuleFeature2Class extends ModuleBaseClass {
#Test
public void testMethod() {
System.out.println("ModuleFeature2Class: in testMethod().");
}
}
This will print:
#BeforeAll static method invoked once.
#BeforeAll static method invoked for every class.
ModuleFeature1Class: in testMethod().
#BeforeAll static method invoked for every class.
ModuleFeature2Class: in testMethod().
In the same manner you can use the annotation #AfterAll to execute after your tests.
You can define the order for methods in a test class, but not for order of test classes.
There is an open request for this feature, but there's no word yet if JUnit will implement it: https://github.com/junit-team/junit5/issues/1948
I'm having a test class, which runs test methods based on static data.
public SampleTest {
public static int static_data;
#test
public static test() {
// Test logic using static_data
}
}
this static data i want to pass it from testsuite.
My test suite looks like this,
#RunWith(Suite.class)
#Suite.SuiteClasses({SampleTest.class, SampleTest.class})
public class SampleTestSuite {
}
Before calling SampleTest, each time i want to pass a different sample_data,
So based on that, different logic can be tested.
I tried with #beforeclass in testSuite, but it's calling only once.
Is there any annotation, which will be called before calling eatch test class.So I can pass a different value ?
I have a class, which I use as a basis for my unit tests. In this class I initialize the whole environment for my tests, setting up database mappings, enter a number of database records across multiple tables, etc. That class has a method with a #BeforeClass annotation which does the initialization. Next thing, I extend that class with specific classes in which I have #Test methods.
My question is, since the before class is exactly the same for all these test classes, how can I ensure that they are run only once for all the tests.
One simple solution is that I could keep all the tests in one class. However, the number of tests is huge, also they are categorised based on functional heads. So they are located in different classes. However since they need the exact same setup, they inherit the #BeforeClass. As a result the whole setup is done at least once per test class, taking much more time in total than I would prefer.
I could, though, put them all in various subpackages under one package, hence if there is a way, how I can run set up once for all the tests within that package, it would be great.
With JUnit4 test suite you can do something like this :
#RunWith(Suite.class)
#Suite.SuiteClasses({ Test1IT.class, Test2IT.class })
public class IntegrationTestSuite
{
#BeforeClass
public static void setUp()
{
System.out.println("Runs before all tests in the annotation above.");
}
#AfterClass
public static void tearDown()
{
System.out.println("Runs after all tests in the annotation above.");
}
}
Then you run this class as you would run a normal test class and it will run all of your tests.
JUnit doesn't support this, you will have to use the standard Java work-arounds for singletons: Move the common setup code into a static code block and then call an empty method in this class:
static {
...init code here...
}
public static void init() {} // Empty method to trigger the execution of the block above
Make sure that all tests call init(), for example my putting it into a #BeforeClass method. Or put the static code block into a shared base class.
Alternatively, use a global variable:
private static boolean initialize = true;
public static void init() {
if(!initialize) return;
initialize = false;
...init code here...
}
Create one base class for all tests:
public class BaseTest {
static{
/*** init code here ***/
}
}
and every test should inherit from it:
public class SomeTest extends BaseTest {
}
You can make one BaseTest class with a #BeforeClass method, then have all the other tests inherit from it. This way, when each test object is constructed, #BeforeClass gets executed.
Also avoid executing it just once for all the test suite, since all the test cases should be independent. #BeforeClass should execute only once each test case, not test suite.
If you can tolerate adding spring-test to your project, or you are using it already, then a good approach is to use the technique described here: How to load DBUnit test data once per case with Spring Test
Not sure if anyone still is using JUnit and trying to fix it without using Spring Runner (aka no spring integration). TestNG has this feature. But here is a JUnit based solution.
Create a RunOnce per thread operation like so. This maintains a list of classes for which the operation has run.
public class RunOnceOperation {
private static final ThreadLocal t = new ThreadLocal();
public void run(Function f) {
if (t.get() == null) {
t.set(Arrays.asList(getClass()));
f.apply(0);
} else {
if (!((List) t.get()).contains(getClass())) {
((List) t.get()).add(getClass());
f.apply(0);
}
}
}
}
Back in your unit test
#Before
public beforeTest() {
operation.run(new Function<Integer, Void>() {
#Override
public Void apply(Integer t) {
checkBeanProperties();
return null;
}
});
}
private void checkBeanProperties() {
//I only want to check this once per class.
//Also my bean check needs instance of the class and can't be static.
}
My function interface is like this:
interface Function<I,O> {
O apply(I i);
}
When you use this way, you can perform operations once per class using ThreadLocal.
We have DAO tests that should run against both the real DAO/database, and against a mock dao to verify that the mock dao behaves the same as the real dao. To this end, we have a structure like this:
public abstract class DAOTestBase
{
public void testSimple()
{
// dummy assertion
assertTrue(true, "Hello");
}
}
#Test(groups = "fast")
public class TestMockDAO extends DAOTestBase
{
// setUp/tearDown and helper methods for mock
}
#Test(groups = "slow")
public class TestDAO extends DAOTestBase
{
// setUp/tearDown and helper methods for real DB
}
Unfortunately this doesn't work - TestNG doesn't think that the testSimple method is a test and hence won't run it. So instead I tried to annotate the testSimple method (or the DAOTestBase class):
A #Test annotation without any groups will lead to the same effect - the test won't run for either fast nor slow groups.
A #Test annotation with groups fast and slow will lead to the opposite effect - both TestMockDAO and TestDAO will be run regardless of whether only fast or only slow tests should be run.
A #Test annotation with a different group, say common, plus added dependsOnGroups="common" annotations in both TestMockDAO and TestDAO will also not work unless common is included in the groups to run which leads again to case 2 above (both TestMockDAO and TestDAO are run).
In the end, what I'm looking for is a way to be able to define the group for the inherited tests in the sub class, but it seems as if the #Test annotation is only applied to test methods in that very same class, not also to inherited methods that don't have a #Test annotation. Is there any other way to achieve this (without overriding all methods in the sub classes) ?
I am currently working through a similar situation.
A way to make test cases run is to use something like:
#Test
public void someTest() {
TestNG testng = new TestNG();
testng.setTestClasses(new Class[] { SomeTests.class });
testng.run();
}
Reference: http://testng.org/doc/documentation-main.html#running-testng-programmatically
Unforunately I am currently unable to get it to report the test cases within SomeTests.
Have you tried simply adding a #Test annotation on top of DAOTestBase? Each subclass will override it with its own group and this should make the method in the base a test method.
I am using TestNG 6.14.3 version and I found a solution using priority annotation.
Example:
I have a base test class:
public class TestBase {
#Test(priority = 0)
public void testA() {
assertTrue(true, "testA");
}
}
And another extended test class:
public class Test2 extends TestBase {
#Test(priority = 1)
public void testB() {
assertTrue(true, "testB");
}
}
When I run Test2 test class, I obtain the following esult:
testA: true
testB: true
I solved it this way:
The methods in the base class are in "base" group, but need to check if the test have been initialized.
public abstract DaoTestBase {
private boolean initialized = false;
#Test(groups = "base")
public void testSimple() {
if (!initialized) { return; }
// dummy assertion
assertTrue(true, "Hello");
}
}
The test is initialized in the child, in the BeforeClass annotated method.
#BeforeClass
protected void initialize() {
super.initialized = true;
}
If you annotate the parent class instead of the methods, you must pass inheritGroups=false and the group, since it inherits also the group of the base class and it will not work.
Now, you must run TestNG to check groups base,fast or base,slow. Both tests will be executed, but the one not initialized will do nothing.
It is ugly, and I would not recommend it (it looks better to redefine the methods in child and call the according super method), but in my case I need priority in my test methods, and I want to avoid that repetition in each child class.
Let's say I have a test class called testFixtureA with several methods testA, testB, testC, etc, each with #Test annotation.
Let's now say I subclass testFixtureA into class called testFixtureAB and I don't overwrite anything. testFixtureAB is empty as for now.
When I run tests from testFixtureAB, methods testA, testB and testC are executed by test runner because test runner doesn't distinguish between test methods from class and baseclass.
How can I force test runner to leave out tests from baseclass?
and I don't overwrite anything.
testFixtureAB is empty as for now
There's your answer. If you want to not run testB from the main class, overrride it:
public class testFixtureAB extends testFixtureA {
#Override
public void testB() {}
}
Restructure your test classes.
If you don't want to use the tests from the baseclass, then don't extend it
If you need other functionality from the base class, split that class in two - the tests, and the other functionality
ignoring the whole base class:
#Ignore
class BaseClass {
// ...
}
check out this example
It's quite easy to achieve implementing some few classes:
Create your own TestRunner
Create an annotation like #IgnoreInheritedTests
Create a class that extends org.junit.runner.manipulation.Filter
On the filter class:
public class InheritedTestsFilter extends Filter {
#Override
public boolean shouldRun(Description description) {
Class<?> clazz = description.getTestClass();
String methodName = description.getMethodName();
if (clazz.isAnnotationPresent(IgnoreInheritedTests.class)) {
try {
return clazz.getDeclaredMethod(methodName) != null;
} catch (Exception e) {
return false;
}
}
return true;
}
#Override
public String describe() {
// TODO Auto-generated method stub
return null;
}
}
on your custom runner:
/**
* #param klass
* #throws InitializationError
* #since
*/
public CustomBaseRunner(Class<?> klass) throws InitializationError {
super(klass);
try {
this.filter(new InheritedTestsFilter());
} catch (NoTestsRemainException e) {
throw new IllegalStateException("class should contain at least one runnable test", e);
}
}
In Junit 5, you can make base class as abstract and extends it with a concrete class.
When you run the abstract in your IDE, your subclass will get executed instead.
In the latest JUnit you can use the #Rule annotation on the subclass to inspect the test name and intercept the test run to ignore the test dynamically. But I would suggest that #Bozho's idea is the better one - the fact that you need to do this indicates a bigger problem that probably shows inheritance is not the right solution here.
I know, it's not the answer...
Consider the reason why you extend concrete test classes. You do duplicate test methods that way.
If you share code between tests then consider writing base test classes with helper and fixture setup methods or test helper class.
If for running tests then try organizing tests with suites and categories.
What if you want to execute the same test for different configurations of the same test suite?
For example, let's say you have Class A with test1, test2 and test3 methods that hit an embedded database then you want to create separated "setUp" and "tearDown" for every embedded vendor (H2, HyperSQL, etc) but runs the same testing for each one.
I would like to extend a class that contain those test methods and configure it in a subclass. My problem is that the super class SHOULD NOT be considered as eligible for the test runner. The problem arises when the test runner executes the super class and given that don't found the corresponding setup and teardown methods, it crashs :(
In the base test class' #Test methods:
assumeTrue(getClass().equals(BaseClassTest.class));
It will ignore those in the subclass tests but not completely leave them out.
If for any reason you need two JUnit classes for same functionality, the best approach for me is:
put the common code in a parent class TestFixture with only constants and mocked services.
create two subclasses: TestFixtureA and TestFixtureB
This way you will not have duplicated code, nor double runs.
I ran into a similar issue where I had a generic abstract base class TestBase and 2 subclasses TestA, TestB that extended the base class. I wanted all tests from TestBase to run for TestA but to skip some for TestB. You can use the JUnit annotations Nested and Disabled to group tests in the base class into categories and then enable a full disable of that entire category of tests.
public class TestB extends TestBase {
// disable entire suite of inherited tests
// from the nested class declared on the parent
#Nested
#Disabled
public class ComponentCTests {}
}
public abstract class TestBase {
#Nested
public class ComponentCTests {
#Test
public void testSomething() {
// test something
}
}
}