I'm quite stuck right now, I don't understand why my code doesn't work as I need to. The fact is that each time there is a new test, it closes firefox and reopens it. That makes my tests take ages to realise... Could you tell me what I'm doing wrong ?
public class SeleniumTestLoginEntry extends SeleneseTestCase {
private String login="scLocator=//DynamicForm[ID=\"formulaire_login\"]/item[index=0||Class=TextItem]/element";
private String passwd="scLocator=//DynamicForm[ID=\"formulaire_login\"]/item[index=1||Class=PasswordItem]/element";
static public DefaultSelenium selenium;
public void setUp() throws Exception {
selenium = new DefaultSelenium("localhost", 4500, "*firefox", "http://localhost:9091/");
selenium.start();
}
public void testFields() throws Exception {
selenium.open("/agepro-prototype/login/Login.html");
selenium.type(login, "Unlogin");
selenium.type(passwd, "Unpassword");
Assert.assertEquals("Unlogin", selenium.getValue(login));
Assert.assertEquals("Unpassword", selenium.getValue(passwd));
selenium.click("scLocator=//ImgButton[ID=\"bouton_login\"]/");
}
public void testSameWindow() throws Exception {
selenium.open("/agepro-prototype/login/Login.html");
selenium.type(login, "truc");
Assert.assertEquals("truc", selenium.getValue(login));
}
public void tearDown() throws Exception {
selenium.stop();
}
}
I tried to put the annotations #BeforeClass and #AfterClass before the setUp() and tearDown, it doesn't change anything. Before there was an #Test before each test but this doesn't helped at all. May I ask you some help ? =)
Edit : Oh also I tried the selenium.open(blablabla) in the setUp() and not in the tests directly, same issue, doesn't change a thing.
Without using annotations, setUp() is going to run before every test (ie, twice).
It's not pretty, but you can create an initial test (which only runs once) and move the instantiation out of setUp() into the new test(). Keep in mind, though, that if that fails to create your selenium instance, then all your subsequent tests will also fail. Not great :)
Related
Am I the first one bumping into this? Is there a way I've overseen to reset the loaded context without writing too much code?
Problem:
#Before
public void before() throws Exception {
context.getRouteDefinition(MyRoute.ID).adviceWith(context, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
weaveAddLast().to("seda:endjob");
}
});
}
#Test
public void testOne(){}
#Test
public void testTwo(){}
will add the "seda:endjob" endpoint TWICE - one for each #Test because #Before will be called before every one. So it kind of makes sense, but I definitely hate it! ALL the examples I've been able to find, either have only one #Test (duh no problem) or do the weaving INSIDE the test which again avoids the problem (but repeats code if my weaving gets hairy)
What I do now is wrapping the weaving into many ugly custom checks, like this one:
if (getOriginalRoute().getOutputs().size() == 1) {
weaveAddLast().to("seda:endjob");
}
The question is then, is there a good way to reset the weaving? Or reload the RouteBuilder? Or something else, just without extra code?
I have a code with many classes.
There is a class which creates the driver -
public class DriverDelegate {
private String baseURL = "someLink";
private WebDriver driver;
private WebDriverWait wait;
DriverDelegate(String url) {
System.setProperty("webdriver.chrome.driver", "${directory}");
driver = new ChromeDriver();
driver.get(baseURL + url);
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
wait = new WebDriverWait(driver, 5);
}
public WebDriver getDriver() {
return driver;
}
I create new driver for every test. And most of my lines are the ones containing assertTrue like this-
public class UserInterfaceTests extends BaseTest{
#Test
public void headerClicker() throws java.lang.Exception {
//Startup
DriverDelegate driverDelegate = new DriverDelegate("url");
WebDriver driver = driverDelegate.getDriver();
//Some random assertTrue
assertTrue("Test(HeaderClicker) - NoSuchElementException click", TestHelper.headerClicker(schedule, driver));
//I hope that it is not neccessary to put up all helper classes like TestHelper or BaseTest
Now I launch my tests from a class called Startup -
public class Startup{
#Test
public void HeaderClicker() throws Exception{ UserInterfaceTests UI = new UserInterfaceTests(); UI.headerClicker();}
My question here is how to close the browser after the assertTrue fails. Things like #AfterTest, #AfterSuite etc do not work because other methods can not use the same driver that was used in the test.
Any ideas?
Ok there are a few things I want to touch on here. First off, #shutdown -h now is correct in their comment that you shouldn't be programmatically creating test classes and running their #Test methods yourself. Let the test running framework handle that (e.g. TestNG, JUnit, etc).
To the point of your actual question, though, is that you want pre-test and post-test methods to handle behavior that occurs before and / or after your actual test method. For these to work, though, you need to let the test framework handle the running of the tests. You mentioned #AfterTest and #AfterSuite as not being correct for your use case, though not for the reason you specified (entirely). #AfterTest in TestNG only is executed once after all the test methods in all the classes inside of a <test> node specified in a suite. #AfterSuite is only executed once after all the test methods in the entire suite. What you are looking for is the #AfterMethod annotation.
Example:
public class FooTest {
private DriverDelegate driver;
#BeforeMethod
public void setup() {
try {
driver = new DriverDelegate("url");
} catch (Exception ignore) { }
}
#AfterMethod
public void tearDown() {
try {
driver.quit();
} catch (Exception ignore) { }
driver = null;
}
#Test
public void foo() {
// do test stuff
}
}
In the above code, when TestNG runs this test class, each method annotated with #Test in this class will have a corresponding #BeforeMethod execution that initializes the driver and an #AfterMethod that closes the driver even if the test fails. Couple of points to make about this type of setup with TestNG:
(1) TestNG does not create separate instances of the test class so if you save state on the class object then you cannot run the test methods themselves in parallel within a class since you would have multiple methods trying to create new drivers and save them to the same variable, corrupting the state of the other tests that are running. You can run with parallel mode of per class (e.g. have 5 threads, each running a separate test class at the same time).
(2) Why did I wrap the #BeforeMethod and #AfterMethod bodies in a try-catch block? Because TestNG takes a fail quickly on configuration method exceptions and can cause other tests that haven't run yet to be skipped so you need to deal with any code that could possibly fail. By wrapping the creating and closing of the web driver you can ignore the error and continue on running other tests. If the driver fails to be created, for instance, the driver variable will be null and that #Test method will fail but others might succeed. Ideally, you should probably have some logging of the exception so that you can investigate why the driver failed to be created, for instance.
Also, if you need to use a driver in many test classes, you can make a base class that does the creation of the driver along with the closing of it after each method and have your test classes extend that. If you have a class with a method annotated with #Test on it, it will run any #BeforeMethod methods on that test class AND on all of the super classes as well. There is guaranteed ordering of the methods between classes (though not if you have multiple #BeforeMethod methods in the same class).
public abstract class A {
#BeforeMethod
public void setupA() { }
}
public class B extends A {
#BeforeMethod
public void setupB() { }
#Test
public void foo() { }
}
In the above, when foo is run, it will have run first setupA and then setupB. After methods work in the same way, but in the reverse order.
I am trying following code:
public class ShashiTest {
#Test
public void test1(){
System.out.println("1===========");
}
#Test(dependsOnMethods="test1")
public void test2(){
System.out.println("2===========");
}
#Test(dependsOnMethods="test2")
public void test3(){
System.out.println("3===========");
}
#AfterMethod(dependsOnMethods={"test2","test3"})
public void test4(){
System.out.println("4===========");
}
}
I am expecting output as:
1===========
2===========
4===========
3===========
4===========
But I am getting exception as test method not found:
com.ShashiTest.test4() is depending on method public void com.ShashiTest.test2(), which is not annotated with #Test or not included.
at org.testng.internal.MethodHelper.findDependedUponMethods(MethodHelper.java:111)
Where I am making the mistake? How I can achieve my goal?
#AfterMethod declares that this method is run after every method annotated with #Test. Right now you have a conflict with test4() being called after test1() and before test2(), while also requiring it to be run after test2(). Refer to this for more in-depth discussion.
edit: I should probably make the call order more clear.
test1()->test4()
test2()->test4()
test3()->test4()
As you can see, requiring test4() to be run after test2() and test3() is in conflict with the #AfterMethod annotation requiring it be called after every method.
dependsOnMethod is not working like that and just used to order methods between them.
The javadoc is clear enough IMO:
The list of methods this method depends on. There is no guarantee on the order on which the methods depended upon will be run, but you are guaranteed that all these methods will be run before the test method that contains this annotation is run. Furthermore, if any of these methods was not a SUCCESS, this test method will not be run and will be flagged as a SKIP. If some of these methods have been overloaded, all the overloaded versions will be run.
But the exception should not happen so I opened an issue for it.
About your need which is running an #AfterMethod for specific methods only (something looks weird, but why not), you can do the following:
public class ShashiTest {
#Test
public void test1(){
System.out.println("1===========");
}
#Test(dependsOnMethods="test1")
public void test2(){
System.out.println("2===========");
}
#Test(dependsOnMethods="test2")
public void test3(){
System.out.println("3===========");
}
#AfterMethod
public void test4(Method m){
switch(m.getName()) {
case "test2":
case "test3":
System.out.println("4===========");
}
}
}
should work as expected.
Bit late to answer but I just faced this problem today. Error: com.expedia.FlightBooking.tearDown() is depending on method public void com.expedia.FlightBooking.flightBooking(), which is not annotated with #Test or not included.
Solution: Changing dependsOnMethods to dependsOnGroups Ex: #AfterTest(dependsOnGroups = {"flightBooking"}) has solved my problem.
I have a question regarding the #Test(dependOnMethods{""})..
I want my tests to run in a particular order so I hit every test that I have written. The best way to do this so far, atleast that I have found, is the dependsOnMethods! However, since the tests to come after requires the one before it to pass, I cant run all of my tests and see which ones failed. My program just exits! So here is what I'm working with..
#Test(dependsOnMethods = {"shouldSelectAmountOfDoors"})
public void shouldSelectExtColor() throws InterruptedException{
sycOptionalInfoPage.selectExtColor("GREEN");
}
#Test(dependsOnMethods = {"shouldSelectExtColor"})
public void shouldSelectIntColor() throws InterruptedException{
sycOptionalInfoPage.selectIntColor("GOLD");
}
#Test(dependsOnMethods = {"shouldSelectIntColor"})
public void shouldEnterAComment() throws InterruptedException{
sycOptionalInfoPage.enterComments("<(*-<) <(*-*)> (>-*)> woot!");
takeABreakYo();
}
Boom. Very easy to understand and trusty POM! But, if my shouldSelectIntColor() fails due to a changed id from the dev team, I want the shouldEnterAComment to still run! How can I continue to keep my tests chained in a line, but still run after a failure? Thanks :)
You can use priority instead of dependsOnMethods to achieve what you want:
#Test(priority = 1)
public void shouldSelectIntColor() throws InterruptedException{
}
#Test(priority = 2)
public void shouldEnterAComment() throws InterruptedException{
}
Here if your shouldSelectIntColor method fails, it will still execute shouldEnterAComment test method.
You can use priority as mentioned or you can use run-always=true. Its called soft dependancy. This way your methods will still run even if the method before failed.
I have a junit testCase class with multiple test methods in it ( As requirement , we don't want to create separate class for each test.)
I wanna create a tearDown type method for EACH test method , which will run specifically for that test. Not for ALL test.
My problem is , in many tests i Insert record in database, test it and delete it after test.
But, If a test fails mid way , control don't reaches till end my dummy record ain't deleting.
I think only ONE tearDown() is allowed for one class, and this tearDown() don't know what object/record i created or inserted and what to delete!!!
I want to create a tearDown() or #After method just for one specific test. Something like finally{} in java for each method.
For Eg:
public class TestDummy extends TestCase {
public void testSample1(){
InsertSomeData1();
assertFalse(true);
runTearDown1();
}
public void testSample2(){
InsertSomeData2();
assertFalse(true);
runTearDown2();
}
public void runTearDown1(){
deleteDummyDatafromTestSample1....
}
public void runTearDown2(){
deleteDummyDatafromTestSample2....
}
}
Here control will never go to runTearDown1() or runTearDown2() and I don't a one common tearDown() because it won't know what data I inserted and thats specific to each method.
It seems your test relies on a fixed database, and future tests will break if your current test breaks. What I'd recommend is not to focus on this particular problem (a test-specific tearDown method that runs for each test), but your main problem - borken tests. Before your test run, it should always work with a clean database, and this should be the case for each test. Right now, your first test has a relationship with the second (through the database).
What the right approach would be is that you recreate your database before each test, or at the very least reset it to a basic state. In this case, you'll want a test like this:
public class TestDummy {
// this code runs (once) when this test class is run.
#BeforeClass
public void setupDatabase() {
// code that creates the database schema
}
// this code runs after all tests in this class are run.
#AfterClass
public void teardownDatabase() {
// code that deletes your database, leaving no trace whatsoever.
}
// This code runs before each test case. Use it to, for example, purge the
// database and fill it with default data.
#Before
public void before() {
}
// You can use this method to delete all test data inserted by a test method too.
#After
public void after() {
}
// now for the tests themselves, we should be able to assume the database will
// always be in the correct state, independent from the previous or next test cases.
#Test
public void TestSample2() {
insertSomeData();
assertTrue(someData, isValid());
}
}
Disclaimer: JUnit 4 tests (using annotations), might not be the right annotations, might not even be the right answer(s).
You could have smth like this:
interface DBTest {
void setUpDB();
void test();
void tearDownDB();
}
class DBTestRunner {
void runTest(DBTest test) throws Exception {
test.setUpDB();
try {
test.test();
} finally {
test.tearDownDB();
}
}
}
public void test48() throws Exception {
new DBTestRunner().runTest(new DBTest() {
public void setUpDB() {...}
public void test() {...}
public void tearDownDB() {...}
});
}
#iluxa . Gr8.. Your solution is perfect!!! In one test class i created two tests test48 and test49 (same as required in my code above testSample1 and testSample2) and viola! every test method now gets its own setup() and tearDown. Only this solution looks little complicated as need to use DBTestRunner in each method, but I don't see any better solution. I was thinking Junit may have some direct solution. like #After or tearDown() with some parameter or something.
Tks a lot.
Use MethodRule:
public class MyRule implements MethodRule {
#Override
public Statement apply(final Statement base, FrameworkMethod method, Object target) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
try {
base.evaluate();
} catch (AssertionError e) {
doFail();
} finally {
doAnyway();
}
}
};
}
}
Then declare it in your test class:
public class TestDummy{
public MethodRule rule = new MyRule();
......
}