Start single Serenity scenario from command line - java

My team received ownership of a webapp. Tests are written with junit suites and serenity. Good things, there a good test coverage. Problem come when you need to run that single test/scenario that is still failing and you need to wait >30min to run everything.
How can I run a single scenario of this suite using mvn command line?
From code editor, it's hard to start single scenario as both suite and test classes contains important initialization code.
I've also tried argument '-Dtest=T1Test#T1Scenario1' without success.
Code snipplet:
#RunWith(Suite.class)
#Suite.SuiteClasses({
UserConfigASuite.class,
UserConfigBSuite.class,
UserConfigCSuite.class
})
public class AllTestSuite {
}
#RunWith(Suite.class)
#Suite.SuiteClasses({
T1Test.class,
T2Test.class,
//... Lots of other tests
})public class UserConfigASuite {
#BeforeClass
public static void beforeClass() {
//Required init code
}
#AfterClass
public static void afterClass() {
//Cleanup after test suite
}
}
#RunWith(SerenityRunner.class)
public class T1Test {
#Test
#Title("T1: scenario 1")
public void T1Scenario1() {
}
//... Lots of other scenarios
}

Just confirm first that your using supported surefire and junit version. For more details refer https://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html
In case your using maven failsafe plugin then the syntax will vary little bit. Something like this
mvn -Dit.test=ITCircle#test* verify
Refer https://maven.apache.org/surefire/maven-failsafe-plugin/examples/single-test.html for more details.

Related

Cucumber 4: Implement Global Hooks

I'm new to Cucumber BDD testing v4.1.
Questions:
How to impelement before(setup) method in Cucumber 4 (DAO, Spring)?
Please help. Thanks.
Cucumber Hooks – Where to use #Before
#Before, in its most basic usage, allows you to run a block of code before every scenario. Normally in Cucumber, we tend to do the initialization related things – such as object initialization, data setup etc in the Given statement. Because of this a lot of people don’t see the need of using Cucumber’s #Before. But you can use #Before to make in an entry in your reporting that a new scenario is being executed. Since #Before always runs before every scenario, you can use this in your reports to clearly depict when a scenario starts executing.
It’s not necessary that you add #Before in each feature file. Just add it in any one feature file and let Cucumber do its job. Cucumber will figure out where you have saved #Before and then it will use it before all the scenarios. To make your reporting bit more useful and easy to understand, you can actually write the scenario name as well in the report. The Java code for this is given below –
#Before
public void before(Scenario scenario) {
System.out.println("------------------------------");
System.out.println("Starting - " + scenario.getName());
System.out.println("------------------------------");
}
Cucumber API provides an Interface called Scenario, using which you can get can instance of this class. In the above code, we have just used the getName() method of this interface to print the scenario name in our log.
Test Hooks with Single Scenario (Example):
Feature File
Feature: Test Hooks
Scenario: This scenario is to test hooks functionality
Given this is the first step
When this is the second step
Then this is the third step
Step Definitions:
package stepDefinition;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
public class Hooks_Steps {
#Given("^this is the first step$")
public void This_Is_The_First_Step(){
System.out.println("This is the first step");
}
#When("^this is the second step$")
public void This_Is_The_Second_Step(){
System.out.println("This is the second step");
}
#Then("^this is the third step$")
public void This_Is_The_Third_Step(){
System.out.println("This is the third step");
}
}
Hooks
package utilities;
import cucumber.api.java.After;
import cucumber.api.java.Before;
public class Hooks {
#Before
public void beforeScenario(){
System.out.println("This will run before the Scenario");
}
#After
public void afterScenario(){
System.out.println("This will run after the Scenario");
}
}
EDIT:
Workaround mentioned in Issue #515 and elsewhere is to use JUnit‘s #BeforeClass and #AfterClass annotations in the runner class, like this:
#RunWith(Cucumber.class)
#Cucumber.Options(format = {
"html:target/cucumber-html-report",
"json-pretty:target/cucumber-json-report.json"})
public class HooksTest {
#BeforeClass
public static void setup() {
System.out.println("Ran the before");
}
#AfterClass
public static void teardown() {
System.out.println("Ran the after");
}
}
Note: While #BeforeClass and #AfterClass may look like the cleanest solution at first, they are not very practical to use. They work only when Cucumber-JVM is set to use the JUnit runner. Other runners, like TestNG, the command line runner, and special IDE runners, won’t pick up these hooks. Their methods must also be are static and would need static variables or singletons to share data anyway.
to run JUnit test cases from the command line
I got the answers already which is implement ConcurrentEventListener.

How to run a method after passing through a tag in the feature file?

I have a scenario in my feature file that contains two tags
#tag1, #tag2
Scenario: This is a test
Given I open the website
When I log in
Then the account page is open
Now #tag is part of a cucumber serenity runner and this works in isolation (before the implementation of #tag2):
#RunWith(CucumberWithSerenity.class)
#CucumberOptions(features="...features/", glue = {".../steps"}, tags = {"#tag1"} )
public class Tag1Runner extends Hooks {
#BeforeClass
public static void startAppium() {
AppiumServerController.startAppiumServer();
}
#AfterClass
public static void stopAppium() {
AppiumServerController.stopAppiumServer();
}
Now what I also want to do is run #tag2, but this only runs after the test has been completed. This is because the method that occurs in #tag2 should not be part of the scenario to test, but should complete a clean up after the test has ran.
Now if I include the following method below, when I run the feature file as it is displayed above, nothing happens.
How can I implement #tag2 to work as mentioned?
public class Hooks{
#After("#tag2")
public void completeCleanUp() {
//code to perform clean up...
}
}
If you are trying to run an After hook after each scenario tagged with "#tag1" in your example, you should mark the After hook with "#tag1". For more information on tagged hooks, please refer to the Cucumber documentation.

How to run JUnit classes or test methods from scratch

I have JUnit tests located in different test folders, when I'm running them one by one everything is green all tests are passed in particular folder, but when its done in scope (all at once), some tests are failing due to some data is changed during previous tests execution. So it's a way to run JUnit tests from scratch, I've tried
mvn "-Dtest=TestClass1,TestClass2" test
but some tests are failed. When its done like:
mvn "-Dtest=TestClass1" test
all passed. Or when:
`mvn "-Dtest=TestClass2" test
all passed.
As long as TestClass1 and TestClass2 share common state there might be no way to run them together e.g. it could be a static field somewhere in the JVM. You must refactor the tests so they are isolated and have no side effects e.g. use #Before and #After to clean up resources after the test.
You could play with Maven Surefire Plugin options to spawn a new JVM for each test but it would be very inefficient.
For this specific problem, you can create a TestSuite.
Create Two Test Suite Classes
Attach #RunWith(Suite.class) Annotation with the class.
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
#RunWith(Suite.class)
#Suite.SuiteClasses({
TestJunit1.class
})
public class JunitTestSuite1 {
}
#RunWith(Suite.class)
#Suite.SuiteClasses({
TestJunit2.class
})
public class JunitTestSuite2 {
}
public class TestRunner {
public static void main(String[] args) {
Result result1 = JUnitCore.runClasses(JunitTestSuite1.class);
Result result2 = JUnitCore.runClasses(JunitTestSuite2.class);
for (Failure failure : result1.getFailures()) {
System.out.println(failure.toString());
}
for (Failure failure : result2.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result1.wasSuccessful());
System.out.println(result2.wasSuccessful());
}
}

Testing different Java Versions in Junit

is there a way to specify the JVM version in a junit test, when multiple java types are available on an OS ?
I'd like to do something like this:
#JVM=1.5
public void test1(){
run();
}
#JVM=1.7
public void test2(){
run();
}
etc..
No, you'll have to run the JUnit tests multiple times with multiple VMs. You can then use Assume to only run the tests for the correct VM:
public void test1(){
// not compiled or tested
Assume.assumeThat(System.getProperty("java.version"), CoreMatchers.startsWith("1.5"));
run();
}
public void test2(){
Assume.assumeThat(System.getProperty("java.version"), CoreMatchers.startsWith("1.7"));
run();
}
Please note that I haven't compiled this, so there may be errors. Then, in your build tool, run these tests twice in two different VMs.
On JUnit 5, you can use EnabledOnJre and DisabledOnJre annotations.
#EnabledOnJre(JRE.JAVA_8)
void testMyMethodInJava8() {
...
}
#DisabledOnJre(JRE.JAVA_8)
void testMyMethodInOtherVersions() {
...
}
You can also apply these to a whole test class:
#EnabledOnJre(JRE.JAVA_11)
public class MyClassTest {
...
}
You still need to run the test suite separately for each JVM, but this allows you to skip the tests that will not work in one or the other.
JUnit test cases are just a bunch of Java classes, not a standalone program. So they would still be confined within the same JVM. AFAIK there is no simple way to do what you intend to do. What you can do is separate the test cases into test suites for each java version you want to test for. Then change the java version in the project settings and run the appropriate test suites.
Also there is a junit.jvm property, but I am not sure if you can change it mid-execution. Have you taken a look at it?

Can I avoid running junit tests twice in eclipse when using a TestSuite?

I need to do some per-suite initialisation (starting a web-server). It is working fine except that when I run all tests in my project in eclipse my tests run twice. My test suite looks a bit like this:
#RunWith(Suite.class)
#Suite.SuiteClasses({
SubtestOne.class,
SubtestTwo.class
})
public class TestSuite
{
[...]
}
public class SubtestOne
{
#Test public void testOne() { [...] }
}
public class SubtestTwo
{
#Test public void testTwo() { [...] }
}
When I run all test in project in eclipse this causes the junit plugin to run the tests twice like this:
SubtestOne
SubtestTwo
TestSuite
SubtestOne
SubtestTwo
Is it possible to make "run all test in project" not run the sub-tests twice? I want my sub tests to be only ever run as part of the suite.
No, the test class will always be started directly and then through the "link" in the suite. This is as expected.
One workaround might to set in the run configuration to only run tests from the package which contains your suites. Open the run configuration and select Run all tests in the selected project, package or source folder then click Search... and select the package.
I realize that this has been asked over 5 years ago, but as quite a few folks up-voted the question I thought I'd still chime in with a solution. Skip right to the end if you just want the solution; read the whole text if you also want to understand it ;-)
First of all, it is indeed possible to ensure that a particular JUnit test class gets only run inside a test suite. Also, it is irrelevant whether you want to run that test suite inside Eclipse (as asked here) or any other tool or environment; this is really a pure JUnit issue for the most part.
Before I sketch out the solution, it might be a good idea to revisit what the exact problem is here. All JUnit tests need to be visible and instantiable to be picked up by the JUnit framework and its various runners. This also applies to test suites and the individual tests that are part of a test suite. As a consequence, if JUnit picks up the test suite it will also pick up the individual tests, and all tests in the suite will be executed twice, once individually and once as part of the suite.
So, the trick, if you will, is to prevent JUnit from picking up the individual tests while still being able to instantiate and execute them as part of the suite.
One thing that comes to mind is to make the test classes static inner classes nested inside the test suite. However, the nested classes still need to be public (otherwise they can't be run in the suite either), and if they are public classes they will also be picked up individually, despite being nested inside the suite's public class. JUnit will not try to run test classes that are not considered visible, though. So, nesting the test classes inside a non-public class would presumably be sufficient to hide them, but we can't make the suite class non-public because then JUnit would not execute it. What we can do, however, is to nest the individual tests inside another non-public class that's nested inside the test suite, which leads us to the solution of this conundrum:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
#RunWith(Suite.class)
#SuiteClasses({AllTests.InSuiteOnly.Test1.class, AllTests.InSuiteOnly.Test2.class})
public class AllTests
{
static class InSuiteOnly
{
public static class Test1
{
#Test
public void test1()
{
//...
}
}
public static class Test2
{
#Test
public void test2()
{
//...
}
}
}
}
A lot of folks will probably object to all tests needing to be inside a single source file now. What if I want to maintain separate JUnit test classes that don't get executed by themselves but still get executed inside the test suite? A simple solution is to make the individual test classes abstract (public/non-public doesn't matter) so that JUnit won't execute them, and inside the test suite we simply use concrete subclasses of the original abstract test classes:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
#RunWith(Suite.class)
#SuiteClasses({AllTests.InSuiteOnly.SuiteTest1.class, AllTests.InSuiteOnly.SuiteTest2.class})
public class AllTests
{
static class InSuiteOnly
{
public static class SuiteTest1 extends Test1 {}
public static class SuiteTest2 extends Test2 {}
}
}
abstract class Test1
{
#Test
public void test1()
{
//...
}
}
abstract class Test2
{
#Test
public void test2()
{
//...
}
}
This scheme works with Maven, Eclipse, and all other environments that either directly leverage JUnit's runners or implement their own runners that closely follow JUnit's original behavior and semantics.
I have an idea for you. Actually you do not want to run these test case as stand-alone test cases. You can do the following.
Mark the test cases with annotation #RunWith(DoNothingRunner.class)
Implment DoNothingRunner as following:
public class DoNothingRunner extends Runner {
public Description getDescription() {
return "do nothing";
}
public void run(RunNotifier notifier) {
// indeed do nothing
}
}
I have not tried this personally but I hope this will work.
do you need the suite in the first place ? depending on when you click for run all (class, package, or src/test/java), all underlying tests will be executed. So what's the point of having a suite ?
There is a solution, it's a bit tricky, but it may easily resolve your problem: create one suite class, and include all your suite classes in it. Then you can use this suite class to run all your tests.
#RunWith(Suite.class)
#Suite.SuiteClasses({
AXXSuite.class,
BXXSuite.class,
CXXSuite.class
})
public class AllSuites {
}

Categories