The solution I am using to create a JUnit test suite dynamically can be found in this similar question here: How do I Dynamically create a Test Suite in JUnit 4?
The solution I am trying to adapt looks like such:
#RunWith(AllTests.class)
public class SomeTests
{
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new JUnit4TestAdapter(Test1.class));
suite.addTest(new JUnit4TestAdapter(Test2.class));
return suite;
}
}
However, I would not only like to be able to dynamically create a test suite, but also be able to allow for the user running my program to specify which tests they would like to run using a properties file.
Is there a way I can annotate my classes with a String such that I can get the actual class type given the annotation String? Are there any viable solutions for this or is it just bad practice in general?
As I understand you would like to mark your test classes as belonging to one or more groups, then user defines the group of test cases to execute. Is it correct?
Bad or good this practice is, it is already implemented in TestNG. There is no such feature in JUnit. But you could easily add annotation scanner to your code and select proper test classes dynamically (e.g. by using https://github.com/ronmamo/reflections to collect all your annotated tests in class path with just single line of code).
Related
I have two test classes each containing a number of tests. I'd like to run both of these together without having to have the #BeforeClass setup method being ran both times. I am calling the classes like this:
public static void main(String[] args) {
TestListenerAdapter tla = new TestListenerAdapter();
TestNG testng = new TestNG();
testng.setTestClasses(new Class[] { TestClass1.class, TestClass2.class });
testng.addListener(tla);
testng.run();
}
The reason for this is because I have both of them calling in a pop up menu and only want to select the option one time. If this is unclear I will try to further explain.
I have a collection of individual tests across 5 classes. I want each class to be able to run separately, but I also want to make them run collectively should I desire. In the #BeforeClass I have each of them calling another class that will select what URL I want to use (I am testing with TestNG and using Selenium WebDriver).
When this code runs it will execute the #BeforeClass in each class I list, and I would like to, if possible, ignore the #BeforeClass in all the tests if I execute the tests using the code above.
I would recommend passing a transformer in to your TestNG test case that implements, IAnnotationTransformer2. That transformer can allow you to control the behavior of the non #Test Annotations at runtime.
IAnnotationTransformer2
You can use a #BeforeTest in a common class of your 2 test classes.
I understand you want to run the stuff inside #Before only once for your 2 test classes that will be executed at same time together.
If you are using maven + junit 4.x, there is an option for setup things before and after test suit start and complete.
Or you can simply create a #ClassRule at suite level, please see the doc
With Parameterized tests in Java, can the 'custom test name' feature exposed in jUnit 4.11 (#Parameters(name="namestring")) be combined with any of the features from Google junitparams?
I have a Java test which cycles through a file containing a set of view names for comparison. Instead of reporting a single test, want each comparison to report out as a separate test instance, each test name customized for the view name supplied as input.
Ideally, would like to use junitparams #FileParameter to load in a file containing the set of names, passing strings into jUnit 'name=' to use as test names and also into the test as input. Both the '#FileParameter' and 'name=' features are relatively simple to implement independently.
Per its doc page, junitparams is 'compliant' with jUnit 4.11, but I haven't figured out a way to combine the two features above. While I can supply both #FileParameter and #Parameters notations to the same test without a syntax or runtime error, the run result seems to ignore the presence of the latter.
Has anyone done this? Is there a better / simpler option? First real question to the Exchange, so please bear with me...
=cjs
JUnit tests that use #Parameters annotation must be run with
#RunWith(Parameterized.class)
However junitparams uses it's own runner
#RunWith(JUnitParamsRunner.class)
A JUnit test can only use a single runner so I don't see how they both can work together unless someone merges the two runners into one.
The easiest solution is to forego junitparams and implement the logic that reads data from the input file and turns it into a parameter list so you can return that from a method annotated with #Parameters.
Another solution is to modify JUnitParamsRunner to behave more like the Parameterized runner does e.g. generate a test with a different name for each parameter read from the input file.
See also:
http://www.mkyong.com/unittest/junit-4-tutorial-6-parameterized-test/
Looking at it again, I agree. A little finagling, found junitparams not needed to do what I wanted.
Ugly partial code sample:
#RunWith(Parameterized.class)
public class ParamSampleTest {
#Parameters(name = "{index} myTest : using [arg0 {0}] and [arg1 {1}]")
public static Collection<Object[]> data() throws FileNotFoundException {
return ParamSampleTest.mydataset();
}
private static Collection<Object[]> mydataset() throws FileNotFoundException {
<snip data read, get length>
ArrayList<Object[]> myList = new ArrayList<Object[]>(length);
<snip create String[][], populate, add to myList>
return myList; // return ArrayList of Object[]
}
}
In JUnit 3, I could get all of the tests within a test suite with the following code:
TestSuite allTestsSuite = (TestSuite) AllTests.suite()
Enumeration enumeration = allTestsSuite.tests();
ArrayList listOfTests = Collection.list(enumeration);
However, I can't find an equivalent way of doing this in JUnit 4. Classes no longer have a .suite() method; they simply use the #Suite annotation. This wouldn't be a problem except that the Suite class no longer has a tests() method. There is a children() method, but that returns a list of Runners, which seem to be something different than why I'm looking for.
So how can I get the tests within a test suite in JUnit 4, like I could with JUnit 3?
The simplest way to perform any kind of filering is to create your own JUnit Categories.
See this Junit Category tutorial for more details but basically, you create your own categories named whatever you want
public interface GuiTest{ }
public interface DbTest { }
And now you can annotate either entire test classes or individual tests with that category:
#Category(GuiTest.class)
public void myJPanelTest{
#Test
public void testFoo(){
...
}
//look we can have other categories too
#Test
#Category(DbTest.class)
public void accidentalDbTest(){
}
}
Then in your test suite, you can specify to include or exclude tests that match the given category
#RunWith(Categories.class)
#IncludeCategory(GuiTest.class)
#ExcludeCategory(DbTest.class) //not sure if we need both but can't hurt
#SuiteClasses( {
...
})
public class GuiTestsOnlySuite{}
Using Categories is much better than having to come up with manually filtering tests based on ad-hoc naming conventions because it that is hard to remember to do (and to make sure everyone in your group adheres to the naming conventions) and since the categories are classes, you can use your IDE to search/refactor/ compile time check your category names.
The only downside I've seen is at least in my IDE, the tests take a little longer to run because there is extra reflection work to do to make sure the test matches your category filter criteria before it runs.
After a bit of experimentation, I discovered the following solution:
SuiteClasses suiteClassesAnnotation = AllTests.class.getAnnotation(SuiteClasses.class);
if (suiteClassesAnnotation == null)
throw new NullPointerException("This class isn't annotated with #SuiteClasses");
Class<?>[] classesInSuite = suiteClassesAnnotation.value();
Basically, it gets the classes the same way that JUnit itself gets them: by looking into the annotation and determining which values are included within it.
The category solution provided by dkatzel is also a good option if you're ultimately wanting to filter these classes, but if you need a list of classes in a suite for some other purpose such as code analysis, this is the simplest and most direct way to do it.
I was looking for a verification test for custom implemented collections, and stumbled upon this: http://www.gamlor.info/wordpress/2012/09/google-guava-collection-test-suite/
I haven't used junit before (so I'm a total noob with junit). I added junit4 to my test project and... got stuck on how to actually run the test suite created by the Google Guava Collection Test Suite. I run annotated test from my test class just fine, but not the test suite from guava.
The junit docs say that suites are created by annotating a suite class with the Suite annotation, listing the cases they should include, but obviously I can't list a dynamically generated class that way. I would be happy to just create a simple test and run the entire suite as a single test, only... how do I get junit to run the suite instance?
If you have a factory method that returns a Test object (let's call it TestMaker.foo(), then you can write something like the following to take the Test and add it to your own TestSuite class:
import junit.framework.JUnit4TestAdapter;
import junit.framework.TestSuite;
import org.junit.runner.RunWith;
import org.junit.runners.AllTests;
#RunWith(AllTests.class)
public class TestRunner {
public static TestSuite suite() {
TestSuite ts = new TestSuite();
ts.addTest(TestMaker.foo());
return ts;
}
}
Now, when you run the TestRunner tests, it will also run the Test returned by TestMaker.foo() along with any other tests that might be defined directly in TestRunner.
For related discussion (for example, how to refer to a Test Class rather than pass a Test object), check out: How do I Dynamically create a Test Suite in JUnit 4?
This question already has answers here:
How do I Dynamically create a Test Suite in JUnit 4?
(7 answers)
Closed 6 years ago.
I have huge set of JUnits in my projects. Out of which, I would like to execute certain set by looking up the classes from a property file.
Prior to JUnit 4:
public class TestSuite
{
public static Test suite()
{
TestSuite suite = new TestSuite();
Class [] array = readFromPropertyFile();
for (Class tempClz : array)
{
suite.addTestSuite(tempClz);
}
}
}
However in Junit4, I'm forced to annotate the classes at compile time as follows:
#RunWith(Suite.class)
#Suite.SuiteClasses({
Test1.class,
Test2.class
})
public class TestSuite
{
}
I cannot, switch back to Junit 3.x because, all the test classes are no more extending TestCase meaning Test1.class is not of type Class<? extends TestCase>
Is there a way to dynamically configure the testsuite in this case ?
The cpsuite project uses a custom annotation to determine the tests to run at runtime based on patterns. This isn't what you want, but it is a good start. You can take the source code for it and replace the "find tests" part with reading from your property file.
Note that the annotation/code is different for different versions of JUnit 4.X. If you are still on JUnit 4.4 or below, you'll need the older one.