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.
Related
I have simple Android application with some espresso tests.
I want to write some base class so all of my test classes will inherit its #beforeClass and #afterClass methods, but the problem is when I do it like code example below, JUnit doesn't see any tests at al. I got Empty test suite. message. What's the problem?
Code example:
public class RealmTest {
protected static Realm realm;
#BeforeClass
public static void beforeClass() {
realm = Realm.getDefaultInstance();
realm.setAutoRefresh(true);
}
#AfterClass
public static void afterClass() {
realm.close();
}
}
#RunWith(AndroidJUnit4.class)
public class MainActivityTest extends RealmTest {
#Rule
public IntentsTestRule<MainActivity> activityTestRule = new IntentsTestRule<>(MainActivity.class);
#Test
public void startedFine() {
assertNotNull(realm);
onView(withId(R.id.button)).perform(click());
intended(hasComponent(new ComponentName(getTargetContext(), EducationActivity.class)));
}
}
If I'll run all tests, tests from MainActivityTest won't run.
Thanks for your help, pls say if some additional info is needed.
Guessing: the JUnit environment is not looking for static methods. So maybe you simply drop that keyword from your base methods (guess you could keep your Realm static nonetheless; I assume you really only want one of those).
But then, another suggestion: don't use inheritance for test cases.
The point that makes test cases valuable to you is: they should quickly allow you to find and fix bugs in your production code.
But when your "setup" is hidden from your testcases - because things are not only happening in some #Before method ... but in a #Before method somewhere, in some different class ... well, that can seriously increase the time you will need to understand a failing testcase. Because: instead of just studying your test case, you find yourself digging around within test code in order to understand what exactly is happening besides the code in that failing test method itself!
Thus: be really careful to balancing "code duplication" versus "test case is easy to understand" aspects!
I have a Selenium test case that I need to write, but before it executes I need to get some information from the user for the Test to run.
Currently, my code is structured like this:
public class myTest {
private WebDriver driver;
#Before
System.setProperty("webdriver.ie.driver",
"C:\\Users\\ktuck\\Documents\\Selenium\\Selenium Server\\IEDriverServer.exe");
driver = new InternetExplorerDriver(); // I guess I don't need to fire this up as i'm only collecting information from the user?
#Test
// Code to collect user inputted data to use later in my test
#After
public void tearDown() throws Exception {
driver.quit(); // Do I need this?
}
}
My initial thoughts were to put the collection code inside of a main function and then call the rest of my test script which would be in a different file, passing the information collected into it. But I'm not quite sure how to do that as I'm quite new to Selenium/Java :p
Can anyone help?
If you are not using any testing framework , you can choose TestNG. TestNG supports Data driven and parameterized test.
you can pass param via testng.xml.
since you are using maven you can configure maven to pass parameters without using testng.xml.
you can also pass params to TestNG via maven through command line like below
mvn -Dtest=<testName> -D<paramName>=<paramValue> test
if you dont want to use any of the testing framework then you can pass the param via JVM arg
and retrive it using System.getProperty("paramName")
Consider using a test framework like JUnit or TestNG. This would enable you to use methods that are run before and after the actual test (as indicated by the pseudo-code given above).
Using this approach, you can do all the lookup stuff in the #BeforeClass method and quit the webdriver in the #AfterTest method. To keep the test class clean, I recommend to move the #BeforeClass and #AfterTest to an abstract super class which you inherit from.
Abstract Superclass
public abstract class AbstractSeleniumTest {
private WebDriver webDriver;
#BeforeClass
public void setup() {
// do all the initalization stuff, e.g. system property lookup
}
#AfterTest(alwaysRun = true)
public void tearDown() {
// do all the clean-up stuff, e.g. webdriver.quit();
}
}
Test Class
#Test
public class MySeleniumTest extends AbstractSeleniumTest {
public void testSomething() {
// do the actual test logic
}
}
I hope this covers most of your question. For further assistance, please give more information.
I'm testing different parts of a miniature search engine, and some of the JUnit tests are leaving entries in the index that interfere with other tests. Is there a convention in JUnit/Maven for clearing objects between tests?
There are 2 particular annotations that can help you with this, and are intended to be used in cases such as yours:
#After defines that a certain method must be executed after every #Test, while #AfterClass is the method to execute once the entire test class has been executed. Think of the latter as a last cleanup method to purge any structures or records you've been using and sharing between tests so far.
Here is an example:
#After
public void cleanIndex() {
index.clear(); //Assuming you have a collection
}
#AfterClass
public void finalCleanup() {
//Clean both the index and, for example, a database record.
}
Note: They have their counterparts (#Before and #BeforeClass) that to exactly the opposite by invoking the related methods before a #Test method and before starting to execute the #Tests defined on that class. This ones are the setUp used in previous versions of JUnit.
If you can't use annotations, the alternative is to use the good old tearDown method:
public void tearDown() {
index.clear(); //Assuming you have a collection.
}
This is provided by the JUnit framework and behaves like a method annotated with #After.
You should make use of the #Before annotation to guarantee that each test is running from a clean state. Please see: Test Fixtures.
Inside of your junit testing class, you can override the methods setup and teardown. setup will run before every one of your tests while teardown will run after every single junit test that you have.
ex:
public class JunitTest1 {
private Collection collection;
//Will initialize the collection for every test you run
#Before
public void setUp() {
collection = new ArrayList();
System.out.println("#Before - setUp");
}
//Will clean up the collection for every test you run
#After
public void tearDown() {
collection.clear();
System.out.println("#After - tearDown");
}
//Your tests go here
}
This is useful for clearing out data inbetween tests, but also allows you to not have to reinitialize your fields inside of every single test.
I'm driving a suite of Selenium tests (actually WebDriver-backed Selenium) using JUnit 4.8.2. I'd like the tests to automatically take a screenshot of the browser as soon as the test fails an assertion. All the tests inherit from SeleniumBaseTestCase, and the majority then further inherit from from SeleniumBastTestCaseWithCompany (which uses #Before and #After methods to create and then clean up common test data via Selenium).
I've tried adding a subclass of TestWatchman as a #Rule in SeleniumBaseTestCase, overriding TestWatchman's failed method to take the screenshot. The trouble is that the #After methods cleaning up the test data are being run before TestWatchman's failed method is called, so the screenshots are all of the final step of the clean-up, not the test that failed.
Looking into it a little, it seems that TestWatchman's apply method just calls the passed Statement's evaluate method (the only exposed method), which calls the #After methods, leaving TestWatchman (or any other Rule) no chance to insert any code between the execution of the test and of the #After methods, as far as I can tell.
I've also seen approaches that create a custom Runner to alter the Statements created so that methods annotated with the custom #AfterFailure are run before #After methods (so the screenshot can be taken in such an #AfterFailure method), but this relies on overriding BlockJUnit4ClassRunner's withAfters method, which is deprecated and due to become private, according to the documentation, which suggests using Rules instead.
I've found another answer on SO about the #Rule lifecycle that makes it sound like this simply might not be possible in JUnit 4.8, but may be possible in JUnit 4.10. If that's correct then fair enough, I'd just like confirmation of that first.
Any thoughts on an elegant and future-proof way in which I can achieve what I want would be much appreciated!
You are right in your analysis, #Befores and #Afters are added to the list of Statements before any Rules. The #Before gets executed after the #Rule and the #After gets executed before the #Rule. How you fix this depends on how flexible you can be with SeleniumBaseTestCaseWithCompany.
The easiest way would be to remove your #Before/#After methods and replace them with an ExternalResource. This could look something like:
public class BeforeAfterTest {
#Rule public TestRule rule = new ExternalResource() {
protected void before() throws Throwable { System.out.println("externalResource before"); }
protected void after() { System.out.println("externalResource after"); }
};
#Test public void testHere() { System.out.println("testHere"); }
}
this gives:
externalResource before
testHere
externalResource after
This field can be put into your base class, so it gets inherited/overridden. Your problem with ordering between #After and your rules then goes away, because you can order your rules how you like, using #RuleChain (in 4.10, not 4.8).
If you can't change SeleniumBaseTestCaseWithCompany, then you can extend BlockJUnit4ClassRunner, but don't override withAfters, but override BlockJUnit4ClassRunner#methodBlock(). You can then call super.methodBlock, and reorder the Statements as necessary[*].
[*]You could just copy the code, and reorder the lines, but withRules is private and therefore not callable from a subclass.
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