I have found so far 2 ways to setup JUnit test timeout. Either using:
#Test(timeout=XXX)
Or using something like:
#ClassRule
public static Timeout timeoutRule = new Timeout(XXX, TimeUnit.MILLISECONDS);
In my case, I have a Test Runner as a main class to run all my test suites, so I can execute the tests as an executable jar.
I'd like this runner to setup the timeouts dinamically using reflection.
Is it possible to do?
You could add the timeout feature to a custom test runner like so:
public class TimeoutTestRunner extends BlockJUnit4ClassRunner {
public TimeoutTestRunner(Class<?> clazz) throws InitializationError {
super(clazz);
}
#Override
protected Statement withPotentialTimeout(FrameworkMethod method, Object test, Statement next) {
return FailOnTimeout.builder()
// you'll probably want to configure/inject this value rather than hardcode it ...
.withTimeout(1, TimeUnit.MILLISECONDS)
.build(next);
}
}
Using this test runner the tests in the following test case ...
#RunWith(TimeoutTestRunner.class)
public class YourTest {
#Test
public void willTimeout() throws InterruptedException {
Thread.sleep(50);
assertTrue(true);
}
#Test
public void willNotTimeout() throws InterruptedException {
assertTrue(true);
}
}
... will behave as follows:
willTimeout: will fail with a TestTimedOutException
willNotTimeout: will pass
Although you will need your tests to be run via this runner you will be able to control their timeout setting from one place and provide custom timeout derivation strategies such as if test name matches <some regex> then timeout is x else ....
Related
I have a JUnit test class which runs 15 tests. 5 of the tests are optional in that I only wish to run them if a particular variable gets initialized by an argument. If the variable value is null I'd like to ignore these tests. Is this possible and if so, how?
You could use JUnit4's Assume feature ...
It's good to be able to run a test against the code as it is currently written, implicit assumptions and all, or to write a test that exposes a known bug. For these situations, JUnit now includes the ability to express "assumptions"
For example:
#Before
public void setUp() {
org.junit.Assume.assumeTrue(yourCondition());
// ...
}
If yourCondition() does not return true then the test for which #Before is running will not be executed.
Approach 1:
You can use JUnit-ext. It has RunIf annotation that performs conditional tests, like:
#Test
#RunIf(DatabaseIsConnected.class)
public void calculateTotalSalary() {
//your code there
}
class DatabaseIsConnected implements Checker {
public boolean satisify() {
return Database.connect() != null;
}
}
Approach 2
Another approach is to use Assume. You can do it in a #Before method or in the test itself, but not in an #After method. If you do it in the test itself, your #Before method will get run. You can also do it within #BeforeClass to prevent class initialization. For example:
#Before
public void beforeMethod() {
org.junit.Assume.assumeTrue(someCondition());
}
Approach 3
I think an another option for you may be to create an annotation to denote that the test needs to meet your custom criteria, then extend the default runner with your own and using reflection, base your decision on the custom criteria. It may look something like this:
public class CustomRunner extends BlockJUnit4ClassRunner {
public CTRunner(Class<?> klass) throws initializationError {
super(klass);
}
#Override
protected boolean isIgnored(FrameworkMethod child) {
if(shouldIgnore()) {
return true;
}
return super.isIgnored(child);
}
private boolean shouldIgnore(class) {
/* some custom criteria */
}
}
Is there a way to run a method after all of the cucumber tests have been run?
The #After annotation would run after every individual test, right? I wan't something that would only run once, but at the very end.
You could use the standard JUnit annotations.
In your runner class write something similar to this:
#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");
}
}
What you could do is to register event handler for TestRunFinished event. For that you can create a custom plugin which will register your hook for this event :
public class TestEventHandlerPlugin implements ConcurrentEventListener {
#Override
public void setEventPublisher(EventPublisher eventPublisher) {
eventPublisher.registerHandlerFor(TestRunFinished.class, teardown);
}
private EventHandler<TestRunFinished> teardown = event -> {
//run code after all tests
};
}
and then you will have to register the plugin :
if you are running cucumber CLI you can use -p/--plugin option and pass fully qualified name of the java class : your.package.TestEventHandlerPlugin
for Junit runner :
#RunWith(Cucumber.class)
#CucumberOptions(plugin = "your.package.TestEventHandlerPlugin") //set features/glue as you need.
public class TestRunner {
}
With TestNG suite annotations would work as well.
#BeforeSuite
public static void setup() {
System.out.println("Ran once the before all the tests");
}
#AfterSuite
public static void cleanup() {
System.out.println("Ran once the after all the tests");
}
cucumber is a scenario base test, you should write your own scenario in .feature file step by step and these steps are executed respectively by their step definitions.
So if you want something to happen after all steps, you should write it in the last step and develop this step in its step definition.
Also, for what you want to execute before other steps you should consider a step before all the steps in the .feature file and develop it in its step definition.
I have two junit test suites, First one will be AllTestInParallel and implemented it to run in multiple threads. Second one is AllTestsInSequence which is quite slower and I need to run in single thread. Finally I need to start both test suites at once. My intention is to run slow tests in first and then run fast test or vise versa.
#RunWith(MultiThreadedClasspathRunner.class)
public class AllTestsInParallel {
}
public class MultiThreadedClasspathRunner extends Suite {
public MultiThreadedClasspathRunner(Class<?> klass, RunnerBuilder builder) throws InitializationError {
super(builder, MultiThreadedClasspathRunner.getTestClassesInProjectClassPath(klass));
}
......
}
#RunWith(SingleThreadedClasspathRunner.class)
public class AllTestsInSequence {
}
public class SingleThreadedClasspathRunnerextends Suite {
public SingleThreadedClasspathRunner(Class<?> klass, RunnerBuilder builder) throws InitializationError {
super(builder, SingleThreadedClasspathRunner.getTestClassesInProjectClassPath(klass));
}
......
}
Can anyone let me know to initiate both runners at once? I tried using jvm param '-Dtest' as below;
-Dtest=com.selenium.runner.AllTestsInSequence,com.selenium.runner.AllTestsInParallel
But it always get last value and execute. Is it possible to start one after other in one command?
Use the #Suiteannotation to create a new suite containing both of the suites you want to run:
#RunWith(Suite.class)
#Suite.SuiteClasses({
AllTestsInParallel.class,
AllTestsInSequence .class
})
public class AllTestsSuite {
}
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
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.