I work on an automated testing framework and I need to close the browser after passing tests on several test classes.
The package structure of the project is similar to this:
PackageA
SomeTestClass1
SomeTestClass2
...
PackageB
SomeOtherTestClass1
SomeOtherTestClass2
...
Note: There can be multiple levels of packages inside one another.
If I use #AfterClass or #AfterAll JUnit annotations I have to close the browser at the 'end' of each test class.
My framework requires launching the browser (as a static variable) and closing it only one time to speed up execution and avoid losing time for every browser launch and login, as I currently have a big number of tests that need to be run each night.
Is there any possiblity I could achieve this behaviour?
In JUnit 4, you could use the concept of Rule in conjunction with extending TestWatcher abstract class (org.junit.rules.TestWatcher).
Hence you won't have to close the browser in a method annotated with #AfterClass.
e.g.
public class StartFinishTestWatcher extends TestWatcher {
#Override
protected void starting(Description description) {
System.out.println("Starting test: " + description.getDisplayName());
}
#Override
protected void finished(Description description) {
System.out.println("Finishing test: " + description.getDisplayName());
// close the browser here
}
}
Then you would use this class in a RuleChain, in the test class(es) where you want to close the browser.
public class MyTestInWhichIWantBrowserToClose {
#Rule
public RuleChain ruleChain = buildTestRuleChain();
private RuleChain buildTestRuleChain() { // could be made protected and put in a superclass
return RuleChain.outerRule(new StartFinishTestWatcher());
}
}
In JUnit 5 you could create custom Test Suites and implement BeforeTestExecutionCallback and (in your case) AfterTestExecutionCallback interfaces in one of your base class.
You would then implement the custom logic which decides to close the browser in method public void afterTestExecution(ExtensionContext context).
Related
I am using TestNG with Selenium WebDriver, the framework that I use has one base class which has BeforeClass method and all the Suite classes extend from this base class and have overriden BeforeClass methods as shown.
public BaseClass{
#BeforeClass
public void preConditions{
//primary actions like opening browser and setting preferences
}
}
public TestSuiteClass extends BaseClass{
#BeforeClass
#Override
public void preConditions(){
super.preCnditions();
//specific preconditions required by test suite
}
}
The problem I am have is, if an overridden method is failing for any reason, all the test suits/cases gets skipped and entire test execution stops.
How to stop this from happening?
If something fails in #Before... annotated procedure the tests will be skipped instead of failing, because the problem is not with your test cases, but with the process before them. So it looks like your car cannot cross the river on a broken bridge, but it's not your car's fault.
If you really want to do some hacking about it, you can find ideas here!
You can find a way around this, but you need to consider if you realy want to do it. The idea of the method with #BeforeClass annotation is to set relevant data for the test (you even called it preConditions). If it fails, the test won't pass anyway.
One way to do it is to remove the #BeforeClass annotation and call the method from the test itself
public TestSuiteClass etends BaseClass {
public void customPreConditions() {
super.preCnditions();
}
#Test
publuc void someTest() {
customPreConditions();
// do the test
}
}
The test will continue even if customPreConditions() is not successful.
First of all let me explain the test setup,
I work for this very large project which has many smaller modules. And to test, we use JUnit in two ways,
JUnit 4: With #Test annotation and we use a custom test runner that derives from BlockJunit4ClassRunner
JUnit 3: We a large chunk of tests those are dynamically created from XML files and are based on junit.framework.TestCase. We have a custom test runner for this too that inherits org.junit.runners.AllTests.
For some cross cutting non-functional requirements we have implemented some rules (org.junit.rules) which we use through annotating the test class using #Rule. This works well for JUnit4 but not JUnit3.
Is there a straight forward way of implementing it without making too many changes?
In case of BlockJunit4ClassRunner we have FrameworkMethod,
#Override
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
...
}
However in case of AllTests, we don't have,
#Override
public void run(RunNotifier notifier) {
...
...
}
I am currently writing JUnit test cases using the Selenium-RC API. I am writing my scripts like:
//example JUnit test case
public class myScripts extends SeleneseTestCase {
public void setUp() throws Exception {
SeleniumServer newSelServ = new SeleniumServer();
newSelServ.start();
setUp("https://mySite.com", "*firefox");
}
public void insert_Test_Name throws Exception {
//write test code here
}
}
And for each test, I have a new JUnit file. Now, since the beginning of my JUnit files will all basically be the same, just with minor variations towards the end, I was thinking about creating a pre-formatted Java template to write create a file with the redundant code already written. However, I can't find any information on whether this is possible. Does Eclipse allow you to create file templates for certain packages?
Create a super class to add all the common code. Creating template is really bad because of the fact you are duplicating the code at the end of the day.
class Super extends SeleneseTestCase{
// Add all common code
}
class Test1 extends Super{
// only special test case logic
}
Also I would suggest not to create SeleniumServer instance for each test case, It will reduce overall performance of the test suite. You can reuse object as long as you are running test sequentially.
I got a lot of different flows which are resuing moduls. Like this Flow1 = M1->M2->M3->M5 or Flow2 = M1->M2->M4->M6->M3->M5.
Now I want to write a testCase for each modul to shorten the time of testdevelopement and then combine those cases to test the flow. Those tests all need an initial setup, sometimes other paramters and certain informations should be carried through the flow. How can I insert them into the testmodul without hardcoding them into the model since they should be changeable for reuse.
Since testcases do not support constructors and parameterized test cases are not what I am looking for.
So not like
Running the same JUnit test case multiple time with different data
but Running differen JUnit test cases with the same source of data.
Is it possible to do that or am I on the wrong track?
If anything is unclear please ask.
I'd really appreciate help.
Greetings
Tarken
Let's see if I understand your problem correctly. You would like to define a test for M1 (testM1), a test for M2 (testM2) a test for M3 (testM3) etc. You would then like to test the combination of M1->M2->M3 by calling all of the test methods testM1, testM2, testM3 in order, but passing some arbitrary data between those methods. So testM1 gets called, and it produces some data which gets passed to testM2, which produces data which gets passed to testM3. The solution below is designed for this, but can easily be extended to include classes.
There are two ways of doing this. The easiest is to define a #Rule in your classes which gets the context stored in a static field in the Suite class and updates it. If you extend ExternalResource, you can do something like:
private Context context;
#Rule
public ExternalResource resource= new ExternalResource() {
#Override
protected void before() throws Throwable {
// get context from Suite class
context = MySuite.getContext();
};
#Override
protected void after() {
// put context into Suite class
MySuite.setContext(context);
};
};
Your methods would then use that context as normal. This would work in most cases, but creates a dependance from the test to a particular MySuite class.
The more complex option
You can do this using a custom #Suite class with a customer Runner. My answer to How to define JUnit method rule in a suite? shows how to execute custom code before and after a particular method (in that case one with a #depcrecated annotation).
You would need to do something similar. So your Suite would create the context for the test, and before executing a particular test method, the runner retrieves the context from the suite, calls a setter in the test class. The test method uses that context, returns and the runner retrieves the context from the test class and updates the suite class. The obvious place to store the context would be the suite, since the test classes themselves are created each time. I think it's too much work to try and pass the context in as a parameter, you'd have to change a lot more code.
So in your Runner, you would have something like
public class MyRunner extends BlockJUnit4ClassRunner {
private MySuite suite;
public MyRunner(Class<?> klass, MySuite suite) throws InitializationError {
super(klass);
this.suite = suite;
}
#Override
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
Description description= describeChild(method);
if (method.getAnnotation(Ignore.class) != null) {
notifier.fireTestIgnored(description);
} else {
// call suite.getContext()
// call setContext() in class
runLeaf(methodBlock(method), description, notifier);
// call getContext() in class
// call suite.setContext()
}
}
}
It is possible to override the beforeclass behaviour as well.
Use BeforeClass.
The selenium tests I'm gonna be doing are basically based on three main steps, with different parameters. These parameters are passed in from a text file to the test. this allows easy completion of a test such as create three of "X" without writing the code to do the create three times in one test.
Imagine i have a test involving creating two of "X" and one of "Y". CreateX and CreateY are already defined in separate tests. Is there a nice way of calling the code contained in createX and createY from say, Test1?
I tried creating a class with the creates as seperate methods, but got errors on all the selenium.-anything-, ie every damn line. it goes away if i extend seleneseTestCase, but it seems that my other test classes wont import from a class that extends seleneseTestCase. I'm probably doing something idiotic but i might as well ask!
EDIT:
well for example, its gonna be the same setUp method for every test, so id like to only write that once... instead of a few hundred times...
public void ready() throws Exception
{
selenium = new DefaultSelenium("localhost", 4444, "*chrome", "https://localhost:9443/");
selenium.start();
selenium.setSpeed("1000");
selenium.setTimeout("999999");
selenium.windowMaximize();
}
thats gonna be used EVERYWHERE.
its in a class called reuseable. Id like to just call reuseable.ready(); from the tests SetUp... but it wont let me....
public class ExampleTest {
#Before
public void setup() {
System.out.println("setup");
}
public void someSharedFunction() {
System.out.println("shared function");
}
#Test
public void test1() {
System.out.println("test1");
someSharedFunction();
}
#Test
public void test2() {
System.out.println("test2");
someSharedFunction();
}
}
The contents of the function after the #Before annotation is what will be executed before every test. someSharedFunction() is an example of a 'reusable' function. The code above will output the following:
setup
test1
shared function
setup
test2
shared function
I would recommend using JUnit and trying out some of the tutorials on junit.org. The problem you have described can be fixed using the #Before annotation on a method that performs this setup in a super class of your tests