How to change the #Test method dynamically in TestNG - java

This is more of a question on test automation framework design. Very hard indeed to summarize whole question in one line :)
I am creating a test automation framework using Selenium. Mostly I am accessing the data (methods name) from an excel file.
In my main Runner class I am getting a list of test cases. Each test case has a set of methods (can be same or different) which I have defined in a java class and executing each method using java reflection api. Everything is fine till this point.
Now I want to incorporate TestNG and reporting/logging in my automation suite. Problem is I cant use #Test for each method as TestNG considers #Test = 1 Test Case - but my 1 Test case might have more than 1 methods. My methods are more like a test steps for a test case, reason is I dont want repeat the code. I want to create a #Test dynamically calling different sets of methods and executing them in Java Or defining each teststeps for a #Test. I was going through the TestNG documentation, but could not able to locate any feature to handle this situation.
Any help is really appreciated and if you have any other thoughts to handle this situaton I am here to listen.

Did you try the following?
#Test(priority = 1)
public void step1() {
//code
}
#Test(priority = 2)
public void step2() {
//code
}
You need to use "priority" for each method, otherwise it won't work.

Related

getting TestNG to treat class variables like JUnit with Guice

I am trying to setup TestNG so that it gives me new instances of my class variable for each test (basically like JUnit). I need this as I intend to parallelize my tests at the method level. I have been experimenting with both standalone Guice and the built in Guice functionality that TestNG provides to try to accomplish this but I have had no luck. I know that I can use ThreadLocal, but calling .get() for every variable in the test is pretty unappealing. I am weary of using GuiceBerry as it does not really have a lot of updates/activity and it's last release is not even acquirable via Maven. I am pretty set on TestNG as for all the inconvenience this is causing me it still does a lot of great things. I am open to things other tools though to accomplish my goal. Basically I want things setup so the below tests would work consistently. Any help would be greatly appreciated.
// just has a variable thats a class called child with a simple string variable
// with a value of "original
Parent p;
#Test
public void sometest1(){
p.child.value = "Altered";
Assert.assertTrue(p.child.value.equals("Altered"));
}
#Test
public void sometest2(){
Assert.assertTrue(p.child.value.equals("original"));
}
TestNG doesn't create a new instance for each test. If you want such a behavior than I recommend creating separate test classes. e.g.:
public class SomeTest1 {
Parent p;
#Test
public void something(){
p.child.value = "Altered";
Assert.assertTrue(p.child.value.equals("Altered"));
}
}
public class SomeTest2 {
Parent p;
#Test
public void something(){
Assert.assertTrue(p.child.value.equals("original"));
}
}
Note that TestNG can run JUnit 3 and JUnit 4 tests (you might maintain a mixed suite depending on the style you want to use in a given test class).

Using TestNG, is there a way to ignore #before class when calling one class into another?

I have two test classes each containing a number of tests. I'd like to run both of these together without having to have the #BeforeClass setup method being ran both times. I am calling the classes like this:
public static void main(String[] args) {
TestListenerAdapter tla = new TestListenerAdapter();
TestNG testng = new TestNG();
testng.setTestClasses(new Class[] { TestClass1.class, TestClass2.class });
testng.addListener(tla);
testng.run();
}
The reason for this is because I have both of them calling in a pop up menu and only want to select the option one time. If this is unclear I will try to further explain.
I have a collection of individual tests across 5 classes. I want each class to be able to run separately, but I also want to make them run collectively should I desire. In the #BeforeClass I have each of them calling another class that will select what URL I want to use (I am testing with TestNG and using Selenium WebDriver).
When this code runs it will execute the #BeforeClass in each class I list, and I would like to, if possible, ignore the #BeforeClass in all the tests if I execute the tests using the code above.
I would recommend passing a transformer in to your TestNG test case that implements, IAnnotationTransformer2. That transformer can allow you to control the behavior of the non #Test Annotations at runtime.
IAnnotationTransformer2
You can use a #BeforeTest in a common class of your 2 test classes.
I understand you want to run the stuff inside #Before only once for your 2 test classes that will be executed at same time together.
If you are using maven + junit 4.x, there is an option for setup things before and after test suit start and complete.
Or you can simply create a #ClassRule at suite level, please see the doc

A Parameterized Parameterized test or Parameterized Suite with a before and after

I have an #Parameterized JUnit test which all works. Now I'm trying to create a new test that runs that same #Parameterized test once for 20 database configurations.
Been having a look online and there are various people who have asked for this but there doesn't seem to be a satisfactory solution. I had a look at Suite but it can't run Parameterized test and it doesn't have any annotations that can be run in between the suite tests to prepare for the next suite test.
Standard Parameterized class:
#RunWith(Parameterized.class)
public class MyParameterizedTest {
// works as normal
}
Here is some pseudo code of what I am looking for:
#RunWith(RunParameterizedLots.class)
#ParameterizedClassToTest(MyParameterizedTest.class)
public class RunParameterizedLotsOfTimes<T> {
#ListOfTestStuff
public List<T> getList() {
return list of T;
}
#BeforeRunningMyParameterizedTest
public void beforePtest(T i) {
setupDatabaseConfig(i);
}
#AfterRunningMyParameterizedTest
public void afterPtest() {
teardownDatabaseConfig(i);
}
}
None of this is written I have spent 2 days reading JUnit documentation and don't seem to be any closer. Release notes for 4.12 talk about #UseParametersRunnerFactory which looks like it might help, there is also some stuff with the new BlockJUnit4ClassRunnerWithParameters but there doesn't seem to be any example of how to use it.
I could create a "#RunWith(Parameterized.class)" class that feeds 1,2,3,4 into itself but then how to I link the sub-parameterized tests into the JUnit subsystem so it looks nice and provides sensible display.
I hope you can see from my waffle question what I am trying to do I just don't know where to start or if someone else has done this work already?
Out of the box it's not possible to parameterize a JUnit test suite, because both are Runners and you may only have one #RunWith() annotation at your test.
For that cause I wrote a new Runner that combines the functionality of both to a ParameterizedSuite: https://github.com/PeterWippermann/parameterized-suite
Good news is, it also enables you to use #Before and #After!
However, I'm not sure if your problem isn't somewhat different: Don't you have two parameters? You say, you already have a parameterized test and now you wan't to run that test against a list of database configurations. So that would be your second parameter. You would like to test all combinations of those two parameters, wouldn't you?

Junit test can't pass all test case once

I have a very strange problem, when i try to run a JUnit test with multiple test case, it will only pass the first test case and shown IndexOut of Bound error
public class ABCTest {
#Test
public void basicTest1(){...}
#Test
public void basicTest2(){...}
...
but if i commend the rest test case, test them one by one, it will pass all of them.
public class ABCTest {
#Test
public void basicTest1(){...}
//#Test
//public void basicTest2(){...}
//...
Since you do not provide the complete testcase and implementation class, I have to make some assumptions.
Most likely you are mutating the state of the tested object by the testcase.
Usually you try to get a clean test fixture for each unit test. This works by having a method with the #Before annotation which creates a new instance of the class under test. (This was called 'setUp()' in older versions of junit.)
This ensures that the order of test method execution as well as the number of executions does not matter and each method is working isolated.
Look at what you are doing inside of the test case and see if you are changing data that may be used by the other test cases and not restoring it to the original state. For example you have a text file that you read and write to in basicTest1 that you then read again in basicTest2 but assume the file is the same as it was before you ran basicTest1.
This is just one possible problem. would need to see the code for more insight

Re-using login functionality in Selenium page object model tests

I am exploring the use of Selenium 2 on a web application which requires authentication before a user can use any of the application. I am planning on either JUnit 4 or TestNG (Still investigating which one to use with Grid 2). I may plan to use jbehave as well.
Does anyone have any suggestions on how I can improve the following test so I can use successful login functionality across all my tests? I want to avoid duplicating login in the tests itself.
public class LoginPageTest {
private LoginPage page;
#Before
public void openTheBrowser() {
page = PageFactory.initElements(new FirefoxDriver(), LoginPage.class);
page.open("http://www.site.com/Login");
}
#After
public void closeTheBrowser() {
page.close();
}
#Test
public void whenTheUserEntersValidCredentialsTheUserIsLoggedIn() {
assertThat(page.getTitle(), containsString("Login") );
}
}
The test is simplified but it will return a page object of a successful login.
thanks
check case study # http://blog.infostretch.com/?p=806 for better idea. If you are at initial level of development i would suggest you to try using QAF (formerly ISFW).
Your best option might be to use the LoginPageTest class as a parent class and extend each of your test classes from LoginPageTest.
That way, each test can login to the system using the parent's setup and tear down methods and do its own additional testing as well.
Create Libraries and call the sequence of test cases to execute one test case/scenario.
Eg:
lib.login();
lib.whenTheUserEntersValidCredentialsTheUserIsLoggedIn();
lib.logout();
for doing this take care of object creations. solution for object is use of super eg: super.login()

Categories