How to organize junit test suites using Allure - java

So far, beside Junit and Jenkins, I used log4j to textual reporting results of test cases but now I want to use Allure, for generating clearer and more transparent reports from my selenium tests.
I'm using maven project where single test case is a java class, and consists of steps which every of them is also a java class. it looks like this:
public class FirstTestCase() {
new Step1(driver).run();
new Step2(driver).run();
new Step3(driver).run();
}
public class SecondTestCase() {
… second test case steps ...
}
In every step - „run” - contains selenium code.
Individual test cases are grouped into larger sets. For example:
#RunWith(Suite.class)
#Suite.SuiteClasses({
FirstTestCase.class,
SecondTestCase.class
})
public class SetOfTests {}
Finally, I have one major class (which is called “TestRunner”) in which the respective sets are activated. It looks like this:
public class TestRunner {
#Test
public void main() {
Result result = JUnitCore.runClasses(
SetOfTests.class
);
So, class hierarchy in my project looks like:
TestRunner |-
SetOfTests |-
FirstTestCase |-
|- Step 1
|- Step 2
|- ....
SecondTestCase |-
|- Step 1
|-Step 2
|- ....
Now, my question is:
How will be best approach to add Allure annotations (like a #Stories,#Features, #Steps... ) that
after the Jenkins “build”, when report will be generated, result will be presented in form as a hierarchy above
Note that, jenkins is configured, works and also generates a report but not in such a form as I want.
Just I need to know in simple way in which test and which step the error occurred

If you look at Allure XSD file you will see that currently (1.4.x series) we support the following structure:
TestSuite|
TestCase|
Step|
Substep|
...
So test suite can contain a set of test cases (nested test cases are not supported) and each test case can contain a hierarchy of steps with unlimited depth. I would implement a custom JUnit adapter for your case - this is as simple as creating one Java class like the following which implements JUnit RunListener interface.

Related

Run Junit test cases only from Test suite and not individual class

I have setup an embedded mongo via flapdoodle (de.flapdoodle.embed).
Quite a lot of mongo operations hence i would like to run all of them as a suite and setup the mongo just once in testsuite.
Now when i run the test cases via mvn install , it seems to run the test cases individually.
Is there a way to run test cases only from suite and not as a class.
baeldung.com describes the use of JUnit 5 Tags, which are very well suited for your case.
You can mark tests with two different tags:
#Test
#Tag("MyMongoTests")
public void testThatThisHappensWhenThatHappens() {
}
#Test
#Tag("MyTestsWithoutMongo")
public void testThatItDoesNotHappen() {
}
And execute either set in a suite, e.g.
#IncludeTags("MyMongoTests")
public class MyMongoTestSuite {
}
In your case, the tests could be categorized by whether Mongo is in the application context or not. So, theoretically, it might be possible to create a JUnit 5 Extension to add the tag. That would be the more complex solution though.

Why Junit TestRunner cannot find the features?

I am working with cucumber and selenium project and I am trying to run the test by a Junit Test Runner. Here is the complete code (make sure you have lombok in your IDE). And here is my test runner:
#RunWith(Cucumber.class)
#CucumberOptions(
features = {"src/test/resources/features" },
monochrome = true,
plugin = {
"pretty",
"com.cucumber.listener.ExtentCucumberFormatter:target/report.html"
},
tags = {"#all"},
glue = {"stepDefinitions"}
)
public class TestRunnerJUnit {
#AfterClass
public static void setup() {
Reporter.setSystemInfo("User Name", System.getProperty("user.name"));
Reporter.setSystemInfo("Time Zone", System.getProperty("user.timezone"));
Reporter.setSystemInfo("Machine", "Windows 10" + "64 Bit");
Reporter.setTestRunnerOutput("Sample test runner output message");
}
}
The point is, when i run the test using the test runner, it finds the feature file, but it does not find any Scenario inside it. Here is the output of the run:
#all
Feature:
As a customer, I should be able to register for insurance.
0 Scenarios
0 Steps
0m0.000s
if i run the test directly using the feature file (by right click on it Run as Cucumber then it works well. But, i need to run my test by test runner)
I had a chance to pull your code base and look into the code.
the issue you are running into is something to do with extent library. you are providing feature name in a new line and which extent library can't understand that. write feature name in same line and it should solve your problem
Feature: As a customer, I should be able to register for insurance.
I also suggest you to use newer version of cucumber (Cucumber-JVM v4+) libraries which have concurrent execution support( under single JVM) and current library which you are using going to span up multiple JVM instances depending on your configuration

JUnit + DbUnit - No test found when extending DatabaseTestCase

I'm getting started with DbUnit lately and I'm trying to write a very simple integration test just to populate a table with 3 rows. Reading the DbUnit Getting Started Guide, it tells me to create a dataset file. My dataset xml file looks exactly like this:
<dataset>
<notaFiscal cliente="Cliente 1" valor="26.5" data='2016-04-04'/>
<notaFiscal cliente="Cliente 2" valor="30.5" data='2016-05-01'/>
<notaFiscal cliente="Cliente 3" valor="28.2" data='2015-08-11'/>
</dataset>
Then, I have to create a test class which extends DBTestCase and implement my test methods (annotated with #Test, like any other JUnit test case). The class I created is as follows:
public class GerenciadorNFTest extends DBTestCase {
private GerenciadorNotaFiscal gerenciador = new GerenciadorNotaFiscal();
public GerenciadorNFTest(String name)
{
super( name );
// PBJDT is an abbreviation of PropertiesBasedJdbcDatabaseTester
// just for a better visualization
System.setProperty(PBJDT.DBUNIT_DRIVER_CLASS,
"org.postgresql.Driver" );
System.setProperty(PBJDT.DBUNIT_CONNECTION_URL,
"jdbc:postgresql://localhost:5432/dbunit" );
System.setProperty(PBJDT.DBUNIT_USERNAME, "postgres" );
System.setProperty(PBJDT.DBUNIT_PASSWORD, "123456" );
}
protected IDataSet getDataSet() throws Exception {
IDataSet dataSet = new FlatXmlDataSetBuilder().build(
new FileInputStream("notas_fiscais.xml"));
return dataSet;
}
#Test
public void geraPedido() {
Pedido p = new Pedido("Diogo", 26d, 5);
gerenciador.gera(p);
NotaFiscal notaFiscal = gerenciador.recupera("Diogo");
Assert.assertEquals(notaFiscal.getCliente(), "Diogo");
}
}
After that, I tried to run the test case but got the following error:
junit.framework.AssertionFailedError: No tests found in teste.GerenciadorNFTest
at junit.framework.Assert.fail(Assert.java:57)
at junit.framework.TestCase.fail(TestCase.java:227)
If I tried to remove the extend DBTestCase, JUnit recognize the test case and runs normally, but with the extend it didn't. I tried to clean and re-compile, but it didn't work. I also tried to run the test outside the IDE I use (Intellij Idea) but again I had no sucess.
Has anyone been through this same problem?
Thank you very much in advance. Any help will be appreciated.
There are JUnit 3 vs 4 runner differences that may be the cause (you don't mention JUnit and dbUnit versions, nor how dependency managing them). And different tooling has different running default requirements (e.g. Maven defaults to only running classes as tests with class name suffix of "Test").
Note that it is not required to extend a dbUnit class (I don't) and not doing so should eliminate the encountered problem. Just further down that page you mentioned are two sections describing how:
Using your own parent class or a dbUnit IDatabaseTester instance: http://dbunit.sourceforge.net/howto.html#Database_setup_with_your_own_TestCase_subclass
Using no parent class: http://dbunit.sourceforge.net/howto.html#Database_setup_with_no_parent_class
And combining both is what I've done for years - have my own parent test class for common stuff and then DI (or instantiate) the desired DBTestCase (usually PrepAndExpectedTestCase).

Get top-most executing TestSuite in JUnit

I need to know the suite class that included the currently running JUnit test. For example, if you have
#SuiteClasses({SubSuite.class})
class ParentSuite { }
#SuiteClasses({TestCase.class})
class SubSuite { }
class TestCase {
#Test
public void testMethod() { }
}
and execute ParentSuite with JUnit, then I want to get a reference to ParentSuite.class. Is this possible?
There is the TestWatcher rule that gets you an instance of Description, which is kind of in the right direction, but that does not include the suite class.
I know this is probably not the best way to write unit tests. My original problem is to run a validation on all classes that are in the project under test, but not those of the dependencies. The TestCase will be in a dependency and included by test suites in other projects. The only solution I could think of is filter those classes with the same source location as that of the top-most-suite. To make that more clear:
BaseLibrary
* contains TestCase and TestSuite
* has classes that should not be validated
ConsumerProject
* has a test-scoped and test-classified dependency to BaseLibrary
* contains ParentSuite
* has classes that should be validated
You probably want to use JUnit #Category https://github.com/junit-team/junit/wiki/Categories
Here's a blog on how to make Categories https://weblogs.java.net/blog/johnsmart/archive/2010/04/25/grouping-tests-using-junit-categories-0
This way you can make Categories for each of your projects.
public interface ConsumerProject {}
Then you can use the #Category annotation to mark test classes (or even test methods) as being in particular categories:
#Category(ConsumerProject.class)
public class TestCase { ... }
Then your suites can be set up to run all the tests for particular categories
#RunWith(Categories.class)
#IncludeCategory(ConsumerProject.class)
#SuiteClasses( { ....})
public class ConsumerProjectSuite { }
You can even have the same test get marked with multiple categories
#Category({ConsumerProject.class, OtherProject.class})
public class CommonTests { }

How to group/categorize large number of JUnit tests

In our project, we currently have a large number of (junit) tests that are split into three categories: unit, integration, wicket.
I now want to group these tests so I can run only one (or two) of those categories. The only thing I found are junit test suites and categories as described here: http://www.wakaleo.com/component/content/article/267
My problem is, I don't want to declare every single test in the Test Suits with #SuiteClasses.
Is there a way to add the suite classes with wildcards / patterns?
Assuming my understanding of the question is correct, it actually can be done using JUnit. The code below was used with JUnit 4.11 and allowed us to split all tests into 2 categories: "uncategorized" and Integration.
IntegrationTestSuite.java
/**
* A custom JUnit runner that executes all tests from the classpath that
* match the <code>ca.vtesc.portfolio.*Test</code> pattern
* and marked with <code>#Category(IntegrationTestCategory.class)</code>
* annotation.
*/
#RunWith(Categories.class)
#IncludeCategory(IntegrationTestCategory.class)
#Suite.SuiteClasses( { IntegrationTests.class })
public class IntegrationTestSuite {
}
#RunWith(ClasspathSuite.class)
#ClasspathSuite.ClassnameFilters({ "ca.vtesc.portfolio.*Test" })
class IntegrationTests {
}
UnitTestSuite.java
/**
* A custom JUnit runner that executes all tests from the classpath that match
* <code>ca.vtesc.portfolio.*Test</code> pattern.
* <p>
* Classes and methods that are annotated with the
* <code>#Category(IntegrationTestCategory.class)</code> category are
* <strong>excluded</strong>.
*/
#RunWith(Categories.class)
#ExcludeCategory(IntegrationTestCategory.class)
#Suite.SuiteClasses( { UnitTests.class })
public class UnitTestSuite {
}
#RunWith(ClasspathSuite.class)
#ClasspathSuite.ClassnameFilters({ "ca.vtesc.portfolio.*Test" })
class UnitTests {
}
IntegrationTestCategory.java
/**
* A marker interface for running integration tests.
*/
public interface IntegrationTestCategory {
}
The first sample test below is not annotated with any category so all its test methods will be included when running the UnitTestSuite and excluded when running IntegrationTestSuite.
public class OptionsServiceImplTest {
#Test
public void testOptionAssignment() {
// actual test code
}
}
Next sample is marked as Integration test on the class level which means both its test methods will be excluded when running the UnitTestSuite and included into IntegrationTestSuite:
#Category(IntegrationTestCategory.class)
public class PortfolioServiceImplTest {
#Test
public void testTransfer() {
// actual test code
}
#Test
public void testQuote() {
}
}
And the third sample demos a test class with one method not annotated and the other marked with the Integration category.
public class MarginServiceImplTest {
#Test
public void testPayment() {
}
#Test
#Category(IntegrationTestCategory.class)
public void testCall() {
}
}
Try using ClasspathSuite
I also had the same problem where I had more then 5500 jUnit tests. I categorised then into 3 groups and created 3 suites using the above jUnit extension. Its great.
You could put them in different packages. Most IDEs have a way to run all the tests in a given package. It's also pretty simple to find all the test classes in a package with a shell script for running tests as part of a build or whatever. I don't know if there's a way to do it with ant, but I would imagine so.
TestNG lets you tag tests as being in particular groups, then run those groups. That sound like exactly what you want, apart from the fact that it's not JUnit!
You could abuse JUnit's assumption mechanism to do what you want: have a system property for each group of tests, and then start each test by assuming that the appropriate property is set. Running all tests will run everything, but everything you don't want will be ignored.
Even if you use JUnit categories, you still won't be able to use wildcards/patterns since categories are annotations, which are Java types.
As pointed out by other commenters, this is exactly why TestNG uses strings to define groups instead of annotations:
#Test(groups = { "database.ACCOUNTS", "fast-test" })
public void newAccountsShouldBeCreated() { ... }
Once you have defined your groups this way, you can include and exclude groups using regular expressions (e.g. "database.*", "front-end.*", etc...).
TestNG is indeed not based on JUnit, but it's very easy to convert all your JUnit tests to TestNG. Here are two blog posts that give an overview of the process:
http://beust.com/weblog/2011/01/04/one-click-test-conversions/
http://beust.com/weblog/2011/02/07/are-your-unit-tests-talking-to-each-other-behind-your-back/
See Junit category or How to run all tests belonging to a certain Category in JUnit 4
have you considered using TestNG?
This is built on JUnit but a lot more powerfull: See comparison.
Grouping is easy.
Tranforming your tests from JUnit to TestNG should be straightforward.
Alternatively, you could create 3 ant scripts that will each run their unit tests but this is less flexible.

Categories

Resources