Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TestNG Run all class methods multiple times preliminary doing @BeforeClass with supplied data

I'm writing a test suite for a webapp using TestNG and Selenium WebDriver.

What i need is to run all methods of the test class multiple times for different authenticated users (data is pulled out at runtime: from a DB). So i need to pass a data to the class with data provider, that supplies credentials of all users, then for each user i need to create a web driver (for the purity of the experiment) and authenticate with supplied credentials in @BeforeClass method, run all @Test methods of the class and make an @AfterClass tear down closing web driver.

How can i do that?

My attempts to do this are here: https://gist.github.com/4246674

Attempt1 was to place a @Test(dataProvider="getUsersIdAndName") on class. It doesn't work because as it turned out @Test(dataProvider=) on the class doesn't mean that all methods of the class should be invoked with the supplied data. The result was that method wasn't invoked at all because there is no data to pass to it arguments. And i get strange test report where this method is marked as passed with execution time of 0 sec. (It is a Maven project opened in NetBeans, if this makes sense.)

Does @Test(dataProvider=) on the class means anything at all?

Attempt2 was to add dataProvider on the @Test annotation of the method. It doesn't work because this means that test method is invoked twice during the single class run. The result was that at the second time it fails because it tries to repeat the test while web driver wasn't reinitialized: browser already renders another page.

Also there are disadvantages of the first and second attempt that log in itself is done in test method rather that in @BeforeClass method because i know no way to supply it with data from data provider.

Attempt3 was a desperate attempt to combine @BeforeClass and @Test on the single method. It doesn't work because @BeforeClass also demands @Parameters if an annotated method has a parameter list. The result is that this method is invoked three times: first time as a class setup when it fails because of the above reason and two times because of the data provider when it succeeds.

Then i found out that TestNG doesn't provide a way to invoke all class methods multiple times with different data: http://comments.gmane.org/gmane.comp.java.testng.user/864

I have two other ideas of how can i archive the same effect.

Idea4 is to place a @Test(dataProvider=) on each test method, each method will perform an authentication and isAuthenticated() test by itself and then perform it's own test. Ineffective and ugly.

Idea5 that looks like the best affordable one is to mark with a @Test only one method that will aggregate all other test methods: it receives data from data provider, performs authentication by given user, then runs isAuthenticated test and all other necessary tests. In this case @BeforeClass and @AfterClass are only setting up and tearing down web driver. This approach has disadvantage that i'm loosing ability to use @BeforeMethod and @AfterMethod but this is affordable to me: looks like i will not need them.

Is there a better way to archive same effect?

Sorry for long message.

Thanks in advance.

like image 964
yaromir Avatar asked Dec 09 '12 20:12

yaromir


2 Answers

You can try exploring Factory for your needs. Factory would allow you to run all methods annotated with @Test of a class with different data. You can initalize ur webdriver in ur beforeclass in that case. Explanation here.

like image 118
niharika_neo Avatar answered Nov 03 '22 00:11

niharika_neo


Okay, let me try to answer your questions based on my experience with testNG and webdriver.

Q. Does @Test(dataProvider=) on the class means anything at all?
A. No. dataProvider is a method level annotation and not a class level. As mentioned here. It should be a method that supplies the data for the Test method in Object[][] format.

Q. How to achieve the scenario you have mentioned? (Assuming I understood your scenario..)
A. You should be using @BeforeMethod rather than @BeforeClass for instantiating webdriver object. In that way you can create a different WD object for each method. And dataProvider can pass multiple data to isAuthenticated() method. If you want to pass a config file at the class level, you can keep @BeforeClass with just property file loading logic in it. So that property file will be loaded once for the whole class. Obviously, you should also use @AfterMethod to close webdriver object.

like image 23
A.J Avatar answered Nov 03 '22 00:11

A.J