AfterAll global hook cucumber-jvm - java

I'm using cucumber-jvm in my integration tests and I need to execute some code after all scenarios are finished, just once.
After reading carefully some posts like this and reviewed this reported issue, I've accomplished it doing something like this:
public class ContextSteps {
private static boolean initialized = false;
#cucumber.api.java.Before
public void setUp() throws Exception {
if (!initialized) {
// Init context. Run just once before first scenario starts
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
// End context. Run just once after all scenarios are finished
}
});
initialized = true;
}
}
}
I think the context initialization (equivalent to BeforeAll) done in this way is fine. However, although it's working, I'm not sure at all if the AfterAll simulation using Runtime.getRuntime().addShutdownHook() is a good practice.
So, these are my questions:
Should I avoid Runtime.getRuntime().addShutdownHook() to implement AfterAll?
Are there other better choices to emulate the AfterAll behaviour in cucumber-jvm?
Thanks in advance for the help.

Probably a better way would be to use a build tool, like Ant, Maven or Gradle for set-up and tear-down actions, which are part of integration tests.
When using Maven Fail Safe Plug-in, for setting up integration tests. There is the phase pre-integration-test, which is typically used for setting up the database and launch the web-container. Then the integration-tests are run (phase integration-test). And afterwards the phase post-integration-test is run, for shutting down and closing / removing / cleaning up things.
INFO In case the Cucumber tests are run through JUnit, the following might also be worth considering
In case it is simpler, smaller set up stuff, you can have a look at the JUnit #BeforeClass and #AfterClass. Or implement a JUnit #ClassRule, which has it's own before() and after() methods.
#ClassRule
public static ExternalResource resource = new ExternalResource() {
#Override
protected void before() throws Throwable {
myServer.connect();
}
#Override
protected void after() {
myServer.disconnect();
}
};

As of Cucumber 2.4.0, the following class gave me the equivalent of #BeforeClass in Junit.
You can place this in test/java/cucumber/runtime.
package cucumber.runtime; //cannot change. can be under /test/java
import cucumber.runtime.io.ResourceLoader;
import cucumber.runtime.snippets.FunctionNameGenerator;
import gherkin.pickles.PickleStep;
import java.util.List;
public class NameThisClassWhatever implements Backend {
private Glue glue;
private List<String> gluePaths;
#Override
public void loadGlue(Glue glue, List<String> gluePaths) {
this.glue = glue;
this.gluePaths = gluePaths;
//Any before steps here
}
#Override
public void disposeWorld() {
//any after steps here
}
#Override
public void setUnreportedStepExecutor(UnreportedStepExecutor executor) { }
#Override
public void buildWorld() { }
#Override
public String getSnippet(PickleStep p, String s, FunctionNameGenerator fng) {
return null;
}
public NameThisClassWhatever(ResourceLoader resourceLoader) { }
}

Related

What is the equivalent of ExternalResource and TemporaryFolder in JUnit 5?

According to the JUnit 5 User Guide, JUnit Jupiter provides backwards compatibility for some JUnit 4 Rules in order to assist with migration.
As stated above, JUnit Jupiter does not and will not support JUnit 4 rules natively. The JUnit team realizes, however, that many organizations, especially large ones, are likely to have large JUnit 4 codebases including custom rules. To serve these organizations and enable a gradual migration path the JUnit team has decided to support a selection of JUnit 4 rules verbatim within JUnit Jupiter.
The guide goes on to say that one of the rules is ExternalResource, which is a parent for TemporaryFolder.
However, the guide unfortunately doesn't go on to say what the migration path is, or what the equivalent is for those writing new JUnit 5 tests. So what should we use?
Interesting article by author of TemporaryFolderExtension for JUnit5
and
his code repo on github
JUnit5.0.0 is now in general release so let's hope they turn their attention to making the experimental stuff production-ready.
Meanwhile, it seems the TemporaryFolder rule will still work with JUnit5 docs
use this:
#EnableRuleMigrationSupport
public class MyJUnit5Test {
and this:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-migrationsupport</artifactId>
<version>5.0.0</version>
</dependency>
As far as I understood, there can be no one to one mapping from ExternalResource to an equivalent in JUnit5. The concepts just don't fit. In JUnit4, the ExternalResource basically gives you a before and an after callback, but within the rule, you have no control about what before and after actually means. You could use it with #Rule or with #ClassRule.
In JUnit5, the extension is defined to hook in specific extension points and thus the 'when' is well defined.
Another difference in concepts would be, that you can have a state in JUnit4 rules, but your JUnit5 extensions shouldn't have any state. Instead, all state should go to the execution context.
Nevertheless, here is an option I came along with, where before and after relates to each test method:
public abstract class ExternalResourceExtension
implements BeforeTestExecutionCallback, AfterTestExecutionCallback {
#Override
public void beforeTestExecution(ExtensionContext context) throws Exception {
before(context);
}
#Override
public void afterTestExecution(ExtensionContext context) throws Exception {
after(context);
}
protected abstract void before(ExtensionContext context);
protected abstract void after(ExtensionContext context);
}
JUnit 5.4 comes with a built-in extension to handle temporary directories in tests.
#org.junit.jupiter.api.io.TempDir annotation can be used in order to annotate class field or a parameter in a lifecycle (e.g. #BeforeEach) or test method of type File or Path.
import org.junit.jupiter.api.io.TempDir;
#Test
void writesContentToFile(#TempDir Path tempDir) throws IOException {
// arrange
Path output = tempDir
.resolve("output.txt");
// act
fileWriter.writeTo(output.toString(), "test");
// assert
assertAll(
() -> assertTrue(Files.exists(output)),
() -> assertLinesMatch(List.of("test"), Files.readAllLines(output))
);
}
You can read more on this in my blog post, where you will find some more examples on utilizing this built-in extension: https://blog.codeleak.pl/2019/03/temporary-directories-in-junit-5-tests.html.
The documentation for that is still in the making - see pull request #660.
Temporary folders now have a solution in the way of #TempDir. However, what about the idea behind ExternalResources in general? Perhaps it's for a mock database, a mock HTTP connection, or some other custom resource you want to add support for?
The answer, it turns out is you can use the #RegisterExtension annotation to achieve something quite similar.
Example of use:
/**
* This is my resource shared across all tests
*/
#RegisterExtension
static final MyResourceExtension MY_RESOURCE = new MyResourceExtension();
/**
* This is my per test resource
*/
#RegisterExtension
final MyResourceExtension myResource = new MyResourceExtension();
#Test
void test() {
MY_RESOURCE.doStuff();
myResource.doStuff();
}
And here's the basic scaffolding of MyResourceExtension:
public class MyResourceExtension implements BeforeAllCallback, AfterAllCallback,
BeforeEachCallback, AfterEachCallback {
private SomeResource someResource;
private int referenceCount;
#Override
public void beforeAll(ExtensionContext context) throws Exception {
beforeEach(context);
}
#Override
public void afterAll(ExtensionContext context) throws Exception {
afterEach(context);
}
#Override
public void beforeEach(ExtensionContext context) throws Exception {
if (++referenceCount == 1) {
// Do stuff in preparation
this.someResource = ...;
}
}
#Override
public void afterEach(ExtensionContext context) throws Exception {
if (--referenceCount == 0) {
// Do stuff to clean up
this.someResource.close();
this.someResource = null;
}
}
public void doStuff() {
return this.someResource.fooBar();
}
}
You could of course wrap this all up as an abstract class and have MyResourceExtension implement just protected void before() and protected void after() or some such, if that's your thing, but I'm omitting that for brevity.

Use Mockito to unit test a function which contains static method call & async task

I have a helper class which contains an public static method getProductHandler(String name):
public class ProductHandlerManager {
public static Handler getProductHandler(String name) {
Handler handler = findProductHandler(name);
return handler;
}
}
A CustomerService class uses the above ProductHandlerManager:
public class CustomerService {
...
public void handleProduct() {
Handler appleHandler = ProductHandlerManager.getProductHandler("apple");
appleHandler.post(new Runnable() {
#Override
public void run() {
//...
}
});
}
}
I want to unit test handleProduct() method in CustomerService class. I tried using mockito to mock the ProductManager.getProductHandler("apple") part in test, however, mockito doesn't support static method mocking. How can I use Mockito to unit test handleProduct() function then?
Please don't suggest me to use Powermock, since I read some article which says if I need to mock static method, it indicates a bad design. But I can accept suggestions about code refactoring to make it testable.
You can refactor and specify a Handler yourself. These can often be package private, if you put your tests in the same package as your classes-under-test—even if they're in a different source folder (e.g. src vs testsrc). Guava (Google Commons) has a handy #VisibleForTesting documentation annotation, too, though Javadoc tends to work as well.
public class CustomerService {
public void handleProduct() {
handle(ProductHandlerManager.getProductHandler("apple"));
}
/** Visible for testing. */
void handleProduct(Handler handler) {
handler.post(new Runnable() {
#Override
public void run() {
//...
}
});
}
}
At this point, you can test handleProduct(Handler) intensively as a unit test, then only test handleProduct() as an integration test to ensure the "apple" product handler interacts correctly.

Selenium Exception Handling Design

In Order to prevent exception handling in each method in selenium page objects, i thought to have a general exception handling, a try catch in the test block,
other handlers only if more specific handling required,
Now the issue is that this process needs to be written in each test...
is there a way to make the test methods have this common test handling written once for all tests?
#Test
public void test(WebDriver driver) {
try {
// common code in the try block
// using testNG may be moved to #BeforeMethod And #AfterMethod
Logger.log("Test Started....");
Logger.log("Test Ended....");
Assert.assertAll();
}
catch() {
// in Case Automation Fails, common operations required
ScreenShoot.getScreenShoot();
}
finally
{
// finally for all tests
driver.close();
}
}
If you are using jUnit, you can create a TestWatcher Rule (the TestNG alternative ITestListener is mentioned here).
public class YourTestWatcherImplementation extends TestWatcher() {
#Override
protected void starting(Description description) {
// initialize your WebDriver
// perhaps login to your tested application?
}
#Override
protected void finished(Description description) {
// shutdown your WebDriver
}
#Override
protected void failed(Throwable error,
Description description) {
// take a screenshot
// do more error handling/reporting
}
}
This way, your tests only contain the actual test code and you got all the preparation/tearDown in one place.
Each test class only needs a public member variable with the #Rule annotation like this:
public class OneOfYourTestClasses {
#Rule
public TestWatcher watcher = new YourTestWatcherImplementation();
#Test
public void testSomething() {
...
}
#Test
public void testEvenMore() {
...
}
}
I'd suggest to create parent test class, which all other tests will extend. In this parent test class, create #AfterMethod, which will take screenshot on failure. Here is an example (although without inheritance):
http://artoftesting.com/automationTesting/screenShotInSelenium.html

How can I set up Zk Sessions (org.zkoss.zk.ui) so I can unit test a controller class extending GenericForwardComposer

I'm trying to unit test an existing ZK controller and I want to find a way to handle a call like the following while unit testing my Controller,
Sessions.getCurrent().setAttribute("from", from.getValue());
I'd be happy to either replacing the offending code, or find a way around it for the unit test. My goal is testability by dealing with the NullPointerException
My test is simple (it's not too bad a place to start...)
#Test
public void zkControllerDoesMockingInitialisedSuccessfully() throws Exception {
T2TripBigDaoInterface tripBigDao = createMock(T2TripBigDao.class);
ZkFieldValidator fieldValidator = createMock(ZkTextFieldValidator.class);
FieldRangeValidator rangeValidator = createMock(DefaultFieldRangeValidator.class);
TripController controller = new TripController(tripBigDao, fieldValidator, rangeValidator);
replay(tripBigDao, fieldValidator, rangeValidator);
controller.onClick$getTrips(new Event("getTrips"));
verify(tripBigDao, fieldValidator, rangeValidator);
// Test purpose: Just get a unit test of the controller running to start with....
}
Extract of the controller:
public class TripController extends GenericForwardComposer {
....
public void onClick$getTrips(Event event) throws Exception {
Sessions.getCurrent().setAttribute("from", from.getValue());
Sessions.getCurrent().setAttribute("to", to.getValue());
....
}
....
Extract of the stack trace:
java.lang.NullPointerException
at com.t2.webservice.controller.alert.TripController.onClick$getTrips(TripController.java:72)
at com.t2.webservice.controller.alert.TripControllerTest.zkControllerDoesMockingInitialisedSuccessfully(TripControllerTest.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
This is one of the things I dislike most about ZK: their use of singletons and the impact that has on testability.
What I end up doing is removing any references to their singletons (Sessions, Executions, Selectors) from my controllers. In normal operation these singletons get used, but in tests they can be mocked out.
How you go about this is up to you, I still haven't found a pattern I'm in love with.
Here's one idea..
public class TripController extends GenericForwardComposer {
private final TripSessionManager tripSessionManager;
public TripController() {
// ZK calls the default constructor
this(new ZKTripSessionManager());
}
protected TripController(TripSessionManager tripSessionManager) {
this.tripSessionManager = tripSessionManager;
}
public void onClick$getTrips(Event event) throws Exception {
tripSessionManager.setTo(to.getValue());
tripSessionManager.setFrom(from.getValue());
}
}
Your TripSessionManager would then look like this..
public interface TripSessionManager {
void setTo(String to);
void setFrom(String from);
}
With the default ZK implementation relying on the Sessions singleton..
public ZKTripSessionManager implements TripSessionManager {
public void setTo(String to) {
setAttribute("to", to);
}
public void setFrom(String from) {
setAttribute("from", from);
}
private void setAttribute(String name, String value) {
// only valid if called in a ZK managed thread
Sessions.getCurrent().setAttribute(name, value);
}
}
By abstracting out the implementation, you can test your controller with a mock TripSessionManager..
#Test
public void test() {
TripSessionManager mockTripSessionManager = mock(TripSessionManager);
when(mockTripSessionManager.setTo(anyString()).thenAnswer(...);
when(mockTripSessionManager.setFrom(anyString()).thenAnswer(...);
TripController controller = new TripController(mockTripSessionManager);
}
You could also imagine different ways of managing these new dependencies (eg: avoid new ZKTripSessionManager()) using dependency injection frameworks like Spring or Guice.

Loading configuration only once before a set of test cases

I have a java package which contains all my test case classes. Each class contains a lot of test cases. Each class is loaded and run one by one by JUnit. However each of the classes contains common configuration code which is run again and again and initialised everytime each of the classes are run.
These initializations take a lot of time.
Is there some way to load these configuration changes first and then run the test case so that I do not need to load them everytime.
JUnit4 has #BeforeClass annotation.
Just do something like this:
public class TestClass {
private static SomeConnection connection;
#BeforeClass
public static void setUp() {
//do common setup
connection = new SomeConnection();
}
#Test
public void testSomething() { }
#Test
public void testSomethingElse() { }
#AfterClass
public static void tearDown() {
//do teardown operations
connection.close();
}
}
Method marked with #BeforeClass will run only once. Just make sure you use JUnit4.
Update:
Also note, that it should be static, and as #ChristopheRoussy mentioned, you can use #AfterClass to destroy your common setup.
You can create a static method that is run before the tests within the class are ran.
#BeforeClass
public static void ranOnlyOnce() {
/*...*/
}
Moreover, if you want to run this once before all of your tests, then you should group your tests in a suite, and put this method in this class, and use JUnit to run the suite instead of the tests.
#RunWith(Suite.class)
#SuiteClasses(value = { Test1.class, ... , Testn.class })
public class AllTests {
#BeforeClass
public static void beforeAllTests() {
/*...*/
}
}
Note that annotations can be used only in Junit 4+.
I would recommend grouping your tests into a testsuite and doing the initialization from the testsuite. There is a good discussion of the possibilities here http://www.xoriant.com/blog/software-testing-and-qa/using-customized-junit-testsuite-for-testing.html
There are a number of possibilities. The first and easiest is to use #BeforeClass and #AfterClass as has been suggested by Matyas and jFrenetic. This is the easiest way to do it if none of the test classes share setup code.
If the classes share the same setup and teardown, look at using the TestRule, specifically the ExternalResource, which allows you to run code before and after each class. The difference between this and #BeforeClass and #AfterClass is that it uses the same class, and therefore the code can be shared more easily. This can be done for example:
#RunWith(Suite.class)
#SuiteClasses({A.class, B.class, C.class})
public class UsesExternalResource {
public static Server myServer= new Server();
#ClassRule
public static ExternalResource resource= new ExternalResource() {
#Override
protected void before() throws Throwable {
myServer.connect();
};
#Override
protected void after() {
myServer.disconnect();
};
};
}
This works in a test class as well, so you could have different, but shared setups for different classes.

Categories

Resources