How to execute some code after Cucumber report is built? - junit

I use Cucumber for jUnit runner to run BDD tests like this:
#RunWith(Cucumber.class)
#CucumberOptions(
format = {"pretty", "json:target/cucumber.json"},
glue = {"com.company.bdd.steps"},
features = {"classpath:bdd-scenarios"},
tags = {"~#skip"}
)
public class CucumberTests {
}
I would like to have beautiful HTML reports from https://github.com/damianszczepanik/cucumber-reporting
And i made jUnit #AfterClass method:
#AfterClass
public static void buildReport() throws Exception {
List<String> srcReportJson = Collections.singletonList("target/cucumber.json");
Configuration configuration = new Configuration(new File("target"), "AEOS BDD Integration Tests");
new ReportBuilder(srcReportJson, configuration).generateReports();
}
The problem is that cucumber.json is empty when #AfterClass method executes. Hence i can't build pretty HTML report.
Is there any hook which i can use to execute some code after cucumber json report is already built?
PS: Cucumber v.1.1.8 is used and Java 1.7 so i was not able to try ExtendedCucumberRunner

Have you considered adding shutdown hook? Here is an example on how to add one. Code in run() method supposed to be executed before JVM shuts down.

You can take a look at custom formatter of cucumber:

Thank you for your suggestions but I just decided to use already existing Maven plugin and execute it's goal right after test goal.

wjpowell posted this suggestion in the cucumber-jvm issues:
"You don't need to do this in cucumber. Use the #beforeclass and #afterclass annotation from within the JUnit test used to run the cucumber tests. This has the benefit of running only for the features specified by the paths or tags options.
#RunWith(Cucumber.class)
#Cucumber.Options(format = {"html:target/cucumber-html-report", "json-pretty:target/cucumber-json-report.json"})
public class RunCukesTest {
#BeforeClass
public static void setup() {
System.out.println("Ran the before");
}
#AfterClass
public static void teardown() {
System.out.println("Ran the after");
}
}
"

Related

Is it possible to add Junit5 extensions programmatically to a #TestTemplate test using #RegisterExtension?

Using Junit version 5.9.2 I am trying to programmatically add parameter resolvers extension for a test class constructor with a #TestTemplate annotation.
I am trying to add the extensions programmatically using #RegisterExtension.
Example:
public class MyTestClass {
#RegisterExtension
static final TestDependencyResolver resolverExt = new TestDependencyResolver(/*...*/);
private final TestDependency dependency;
public MyTestClass(TestDependency dependency) {
this.dependency = dependency;
}
#TestTemplate
#ExtendWith(SomeContextProvider.class)
void test() {
//...
}
}
I have tried:
making resolverExt field non static
Movine #ExtendWith(SomeContextProvider.class) to class level
And other possible combinations of 1 and 2.
In all cases the ctor parameter dependency is not injected and TestDependencyResolver::resolveParameter is not called, which to my understanding means the object was created without/before registering TestDependencyResolver, please correct me if I am wrong.
Is what I am trying to achieve possible? thanks.
Turns out the issue was not Junit5 but TestTemplateInvocationContextProvider I was using.
I used PactVerificationInvocationContextProvider which seems to have a bug and throws NullPointerException when resolving Ctor params, I have opened an issue for it if you want more details.

Spring-boot Redis JMS JUnit

I am using Redis Server for message broker in my spring boot application.
Is there any simple way to Junit my publish and receive API?
e.g :
Publisher :
public String publish(Object domainObj) {
template.convertAndSend(topic.getTopic(), domainObj.toString());
return "Event Published";
}
Receiver :
public class Receiver implements MessageListener {
#Override
public void onMessage(Message message, byte[] bytes) {
System.out.println("Consumed Message {}" + message);
}
}
I am using JedisConnectionFactory and RedisMessageListenerContainer and RedisTemplate for my implementation
#Configuration
#EnableRedisRepositories
public class RedisConfig {
#Bean
public JedisConnectionFactory connectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
configuration.setHostName("localhost");
configuration.setPort(6379);
return new JedisConnectionFactory(configuration);
}
#Bean
public RedisTemplate<String, Object> template() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new JdkSerializationRedisSerializer());
template.setValueSerializer(new JdkSerializationRedisSerializer());
template.setEnableTransactionSupport(true);
template.afterPropertiesSet();
return template;
}
#Bean
public ChannelTopic topic() {
return new ChannelTopic("common-channel");
}
#Bean
public MessageListenerAdapter messageListenerAdapter() {
return new MessageListenerAdapter(new Receiver());
}
#Bean
public RedisMessageListenerContainer redisMessageListenerContainer() {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory());
container.addMessageListener(messageListenerAdapter(), topic());
return container;
}
Unit Testing Receiver and Publisher implementation is quite straight.
JUnit 5 coupled with Mockito extension should do the job.
For example for testing that :
public String publish(Object domainObj) {
template.convertAndSend(topic.getTopic(), domainObj.toString());
return "Event Published";
}
I expect that topic and template be fields of the current class.
These fields could be set by constructor.
So you could write something that check that convertAndSend() is eventually executed with the correct parameters :
#Mock
RedisTemplate<String, Object> templateMock;
#Test
void publish(){
Topic topicFixture = new Topic(...);
Object domainObjFixture = new FooBar(...);
Publisher publisher = new Publisher(templateMock, topicFixture);
//when
publisher.publish(domainObjFixture);
// then
Mockito.verify(templateMock)
.convertAndSend(topicFixture.getTopic(), domainObjFixture);
}
But I don't think that the unit test of these two classes be enough because it never tests the final things : the JMS processing performed by Redis backend.
Particularly, the RedisConfig part that you set with specific things as serializers that have important side effects on the processing.
For my part, I try to always write integration or partial integration tests for Redis backend stuffs to ensure a good no regression harness.
The java embedded-redis library is good for that. It allows to start a redis server
on localhost (works on Windows as well as on Linux).
Starting and stopping the redis server is as simple as :
RedisServer redisServer = new RedisServer(6379);
redisServer.start();
// do some work
redisServer.stop();
Move the start() in the #BeforeEach and the stop() in the #AfterEach and the server is ready.
Then it still requires some adjustments to ensure that the redis configuration specified in Spring is well setup during the tests while using your local redis server and not the "real" redis server. Not always simple to set but great when it is done !
The simplest way to unit test this is to use embedded-redis module. What you do is in BeforeAll you can start embedded Redis and stop the embedded Redis in AfterAll method.
You can also PostConstruct PreDestroy annotations to accomplish this.
If you're looking for Junit5 then you can find the code in my repo here
See BootstrapRedis annotation and their usage here
https://github.com/sonus21/rqueue/blob/7ef545c15985ef91ba719f070f7cc80745525047/rqueue-core/src/test/java/com/github/sonus21/rqueue/core/RedisScriptFactoryTest.java#L40

How to two runner property include in one test case class?

#RunWith(DataProviderRunner.class)
#RunWith(SpringJUnit4ClassRunner.class)
public class DatabaseModelTest {
// some tests
}
or
#RunWith(Parameterized.class)
#RunWith(SpringJUnit4ClassRunner.class)
public class DatabaseModelTest {
// some tests
}
We can not use two runner property in one test case class...!! so that
I want to run test case with Multiple data how i pass multiple parameter in Rest web service to execute test case ??
Any solution for extend class for DataProviderRunner or parameterized ??
Thanks
(stayconnected52)
You could use Spring's JUnit rules instead of the SpringJUnit4ClassRunner. This works at least with the Parameterized runner. I don't know whether it works with the DataProviderRunner, too.
You need at least version 4.2.0 of the Spring framework and spring-test.
#RunWith(Parameterized.class)
public class DatabaseModelTest {
#ClassRule
public static final SpringClassRule SCR = new SpringClassRule();
#Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
...
}
I tested the solution of #Stefan and works also well for #RunWith(DataProviderRunner.class)
I found a second solution in DataProvider for Spring Integration Testing, they wrote a class DataProviderRunnerWithSpring and set the test class like:
#RunWith(DataProviderRunnerWithSpring.class)
public class TestClass{
...
}

Allure framework isn’t producing detailed reports when using JunitCore

I am running Junit test using JUnitCore.
And i am trying to use allure framework for reporting.
The documentation suggest to add the AllureRunListener using the JUnitCore.addListener().
But, no matter how i try to do so the allure report is coming out empty.
They show the tests that run , and also fail assert, but without the #step,#attachment.
I tried to search for example of using allure report using the JunitCore and not the maven plugin but couldn’t find anything (Running the test using maven work fine, and allure report everything okay).
How it can be done?
The JunitCore runing -
public static void main(String[] args) {
AllureRunListener allureListener =new AllureRunListener();
JUnitCore core = new JUnitCore();
core.addListener(allureListener);
Result result = core.run(BuildNetworkTest.class);
//Result result = core.runClasses(TestSuite.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
The test -
#Test
public void BuildNetwork(){
try {
Build buildFactory = new Build();
System.out.println("running the BuildNetwork test in TestRunnerPac.BuildNetwork");
StepTemp();
attachmentTemp();
}catch (Exception e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
}
#Step
public void StepTemp(){
assertThat("stepTemp").isEqualTo("stepTemp");
System.out.println("In stepTemp..");
}
#Attachment
public String attachmentTemp(){
return "this is an attachmentTemp , hope it will work..";
}
Be sure to launch your tests with the -javaagent argument pointing to aspectjweaver.jar, e.g.:
java -javaagent:"/path/to/aspectjweaver.jar" <the rest of the arguments>
If you're using Maven Surefire plugin, then take a look at the following example on how to do this.

Launching a JUnit test from an eclipse plugin using a custom JUnit runner implementation

I have written a custom JUnit runner that I want to become part of an eclipse plugin that will launch tests using this runner without having to apply the #RunWith annotation to the class. I have managed to get an additional item under the 'Run As' context menu, using the org.eclipse.debug.ui.launchShortcuts extension point. However, I am not sure how to invoke the test using my custom runner.
So I figured out a way to do what I wanted. However, it does seem a bit hacky. But, I thought that I would post the answer here in case someone else runs into the same problem.
First you have to register a junit kind like this:
<extension point="org.eclipse.jdt.junit.internal_testKinds">
<kind
id="my.junit.kind"
displayName="Your Kind Name"
finderClass="org.eclipse.jdt.internal.junit.launcher.JUnit4TestFinder"
loaderPluginId="org.eclipse.jdt.junit4.runtime"
loaderClass="your.test.loader.MyLoaderClass">
<runtimeClasspathEntry pluginId="org.eclipse.jdt.junit4.runtime" />
<runtimeClasspathEntry pluginId="org.eclipse.jdt.junit.core" />
<runtimeClasspathEntry pluginId="org.eclipse.jdt.junit.runtime"/>
</kind>
</extension>
In the xml you have to specify a custom implementation of org.eclipse.jdt.internal.junit.runner.ITestLoaderwhich in turn returns an implementation of org.eclipse.jdt.internal.junit.runner.ITestReference. The core part is the implementation of ITestReference, because this is where you create an instance of your custom JUnit runner.
public class MyTestReference extends JUnit4TestReference
{
public MyTestReference(final Class<?> p_clazz, String[] p_failureNames)
{
super(new Request()
{
#Override
public Runner getRunner()
{
return new MyCustomRunner(p_clazz);
}
}, p_failureNames);
}
...
}
Then finally you have to link this with a launch shortcut that sets the kind appropriately
public class MyJunitLaunchShortcut extends JUnitLaunchShortcut
{
#Override
protected ILaunchConfigurationWorkingCopy createLaunchConfiguration(IJavaElement p_element) throws CoreException
{
ILaunchConfigurationWorkingCopy config = super.createLaunchConfiguration(p_element);
config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_RUNNER_KIND, "my.junit.kind");
return config;
}
}
This does use a bunch of internal classes, so there is probably a better way. But this seems to work.