How to run same class multiple times using selenium - java

Is there any way that I can run a class 3 times or more in Selenium. So it runs in below order:
method1
method2
method3
method1
method2
method3
method1
method2
method3
import com.test
Class A{
#Test(priority =1)
public void method1(){`System.out.print('method1');`}
#Test(priority =2)
public void method2(){`System.out.print('method2');`}
#Test(priority =3)
public void method3(){`System.out.print('method3');`}
}

As far as I know, there is no easy way in TestNG to do so. Annotation parameter invocationCount only works on method level, not on class, so annotating your class with #Test(invocationCount = 3) doesn't work.
As you're mentioning Selenium, my guess is you are trying to automate some repeated actions on a webpage. If so, then I think ideologically your best bet is to extract code from these three methods and just write another test that calls those internals, like this:
#Test(priority = 1)
public void method1() {
stuff1();
}
#Test(priority = 2)
public void method2() {
stuff2();
}
#Test(priority = 3)
public void method3() {
stuff3();
}
#Test
public void complexTest() {
for (int i = 0; i < 3; i++) {
stuff1();
stuff2();
stuff3();
}
}
private void stuff1() {
System.out.print("method1");
}
private void stuff2() {
System.out.print("method2");
}
private void stuff3() {
System.out.print("method3");
}
It's a good practice to treat each test as atomic test that can either fail or pass, and if you want to test some scenario that does particular set of actions three times, better introduce new test for this and make it clearly and explicitly "tell a story" of test.

Related

How to extend a class having parameterized #BeforeMethod

I want to extend BaseClass from all test cases class.
For some test cases I want to login with Admin credentials and for some with Customer.
Previously this code was working properly as launchBrowserAndLogin() method was not having any parameters.
Is there any way for extending class with parameter?
Here is my code:
public class BaseClass {
public BaseClass() {
}
#BeforeMethod
public void launchBrowserAndLogin(String userType) {
if(userType.equals("Admin")) {
launchBrowserAndUrl(Constants.ADMIN_URL);
login(Constants.ADMIN_USER_NAME, Constants.ADMIN_USER_PASSWORD);
}
if(userType.equals("Customer")) {
launchBrowserAndUrl(Constants.CUSTOMER_TEST_URL);
login(Constants.CUSTOMER_USER_NAME, Constants.CUSTOMER_USER_PASSWORD);
}
}
#AfterMethod
public void tearDown() {
TestDriver.getDriver().quit();
}
}
public class AssignEditDeleteRoleAccessibilityTest extends BaseClass {
CreateUser newUser = new CreateUser();
RoleAssignmentAccessValidation roleAccessValidation = new RoleAssignmentAccessValidation();
#DataProvider(name = "AssignEditDeleteRoleAccessibilityTest")
public static Object[] roleNames() {
return new Object[] {Constants.AGENCY_ASSISTANT_ROLE_NAME, Constants.OPS_MANAGER_ROLE_NAME};
}
#Test ( priority=1, dataProvider = "AssignEditDeleteRoleAccessibilityTest")
public void assignRoleAccessTest(String roleName) {
newUser.createUserAssignRoleAndLogin(roleName);
boolean isAssignRoleOptionAvailable =roleAccessValidation.assignRoleAccess();
assertEquals(isAssignRoleOptionAvailable, false);
}
}
Now I am getting error:
FAILED CONFIGURATION: #BeforeMethod launchBrowserAndLogin
org.testng.TestNGException:
Can inject only one of <ITestContext, XmlTest, Method, Object[], ITestResult> into a #BeforeMethod annotated launchBrowserAndLogin.
If this were my code, I would split up BaseClass into AdminClass and CustomerClass -- this will both solve the issue, and also help organize the tests a little better, because now you will be aware if the scenario under test is either Customer or Admin view based on which class the test case class extends:
public class CustomerClass {
public CustomerClass() {
}
#BeforeMethod
public void launchBrowserAndLogin() {
launchBrowserAndUrl(Constants.CUSTOMER_TEST_URL);
login(Constants.CUSTOMER_USER_NAME, Constants.CUSTOMER_USER_PASSWORD);
}
#AfterMethod
public void tearDown() {
TestDriver.getDriver().quit();
}
}
And Admin class:
public class AdminClass{
public AdminClass() {
}
#BeforeMethod
public void launchBrowserAndLogin() {
launchBrowserAndUrl(Constants.ADMIN_URL);
login(Constants.ADMIN_USER_NAME, Constants.ADMIN_USER_PASSWORD);
}
#AfterMethod
public void tearDown() {
TestDriver.getDriver().quit();
}
}
Then, your test case class can look like this:
public class AssignEditDeleteRoleAccessibilityTest extends CustomerClass{ // or AdminClass
CreateUser newUser = new CreateUser();
RoleAssignmentAccessValidation roleAccessValidation = new RoleAssignmentAccessValidation();
#DataProvider(name = "AssignEditDeleteRoleAccessibilityTest")
public static Object[] roleNames() {
return new Object[] {Constants.AGENCY_ASSISTANT_ROLE_NAME, Constants.OPS_MANAGER_ROLE_NAME};
}
#Test ( priority=1, dataProvider = "AssignEditDeleteRoleAccessibilityTest")
public void assignRoleAccessTest(String roleName) {
newUser.createUserAssignRoleAndLogin(roleName);
boolean isAssignRoleOptionAvailable =roleAccessValidation.assignRoleAccess();
assertEquals(isAssignRoleOptionAvailable, false);
}
}
This will solve your error, but I recognize this also a matter of opinion & personal design preference -- the concept of a test fixture (which is what BaseClass / AdminClass / CustomerClass each represent) can be implemented in many different ways. I personally believe having a fixture for each "starting" scenario is better in terms of organization and maintainability -- if AdminClass ever becomes more complex, this code will be out of the way from CustomerClass.
Another alternative would be to keep BaseClass, but remove the #BeforeMethod and launchBrowserAndLogin() method. Then, you can write CustomerClass and AdminClass to extend BaseClass (so that the #AfterMethod is inherited). Then, CustomerClass and AdminClass() can implement their own versions of launchBrowserAndLogin(), and the test case class would still look the same as this sample.
There are other approaches to resolve this as well, it's just a matter of personal preference in terms of design and maintainability.
Even if this is not your preferred answer, hopefully this at least gives you an alternative approach for future thought.
What you are trying to do won't be as straightforward to achieve. The Data-Provider feeds the #Test method and the #BeforeMethod method runs before the Test Method, so sending a parameter from the second method to the first one to run won't be possible.
Maybe helping yourself with an ITestListener you can work something out.
For more information on what you can parameterize in your #BeforeMethod, refer to the link your error is telling to look at:
https://testng.org/doc/documentation-main.html#native-dependency-injection
There you have listed the possible things it can receive.
You need to have your BaseClass implement org.testng.IHookable and then have the run() method invoke your launchBrowserAndLogin() method.
Here's how your modified base class will look like:
import java.lang.reflect.Method;
import org.testng.IHookCallBack;
import org.testng.IHookable;
import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
public class BaseClass implements IHookable {
#Override
public void run(IHookCallBack callBack, ITestResult testResult) {
Object[] parameters = testResult.getParameters();
String userType = parameters[0].toString();
launchBrowserAndLogin(userType);
callBack.runTestMethod(testResult);
}
public void launchBrowserAndLogin(String userType) {
if (userType.equals("Admin")) {
System.err.println("Launching Admin flow");
launchBrowserAndUrl(Constants.ADMIN_URL);
login(Constants.ADMIN_USER_NAME, Constants.ADMIN_USER_PASSWORD);
}
if (userType.equals("Customer")) {
System.err.println("Launching Customer flow");
launchBrowserAndUrl(Constants.CUSTOMER_TEST_URL);
login(Constants.CUSTOMER_USER_NAME, Constants.CUSTOMER_USER_PASSWORD);
}
}
#AfterMethod
public void tearDown(Method method) {
//include your tear down logic here
System.err.println("tearDown() for " + method.getName());
}
public void launchBrowserAndUrl(String url) {
//logic goes here
}
public void login(String username, String password) {
//logic goes here
}
}

JUnit - test that a method has been called

I'm new to unit testing, and I'm trying to test that a method has been called. The method in question doesn't return anything.
public void example (boolean foo) {
if (foo) {
processFoo(foo);
}
else if (foo==false) {
processSomethingElse(foo);
}
}
I want to be able to test that the processFoo method is being called, but I don't know how to do that.
If mocking is required, then I have to use JMockit. Thanks!
Sorry I'm a little late to the party, but I have a couple of ideas for you.
First, you mention that one option is to use JMockit--that's great as it gives you a lot of flexibility. If you use JMockit, then the visibility of your processFoo() method doesn't much matter. Let's see what that might look like:
public class Subject {
public void example (boolean foo) {
if (foo) {
processFoo(foo);
}
else if (foo==false) {
processSomethingElse(foo);
}
}
private void processFoo(boolean b) {
System.out.println("b = " + b);
}
private void processSomethingElse(boolean bb) {
System.out.println("bb = " + bb);
}
}
So, one caveat with this option, though is that I'm going to assume processFoo() is a method on your test subject and I'm going to use a partial mock to change the test subject--not something I really like to do, but this is an example. In general, it is best to only mock the dependencies of your test subject rather than behavior of the test subject itself--you have been advised! Note that the processFoo() method of the test subject is private. I'm going to substitute a method for the test with JMockit's partial mocking and the visibility of that new method does not have to match the original.
import static org.assertj.core.api.Assertions.assertThat;
import mockit.Mock;
import mockit.MockUp;
import mockit.integration.junit4.JMockit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
#RunWith(JMockit.class)
public class SubjectTest {
private Subject testSubject = new Subject();
private boolean processFooCalled = false;
#Before
public void setup() {
new MockUp<Subject>() {
#Mock
public void processFoo(boolean b) {
processFooCalled = true;
};
};
}
#Test
public void should_call_processFoo() {
testSubject.example(true);
assertThat(processFooCalled).isTrue();
}
#Test
public void should_not_call_processFoo() {
testSubject.example(false);
assertThat(processFooCalled).isFalse();
}
}
Ok, so that was the first option. It's actually a little easier if you forget JMockit for this one, assuming you are able to subclass your test subject and override the processFoo() method:
public class Subject {
public void example (boolean foo) {
if (foo) {
processFoo(foo);
}
else if (foo==false) {
processSomethingElse(foo);
}
}
protected void processFoo(boolean b) { // NOTE: protected access here!
System.out.println("b = " + b);
}
private void processSomethingElse(boolean bb) {
System.out.println("bb = " + bb);
}
}
So, in this case, the strategy is simply to subclass your test subject and replace the implementation of the method you wish to observe being called. It might look like this:
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
public class SubjectTest2 {
private Subject testSubject = new TestableSubject();
private boolean processFooCalled = false;
#Test
public void should_call_processFoo() {
testSubject.example(true);
assertThat(processFooCalled).isTrue();
}
#Test
public void should_not_call_processFoo() {
testSubject.example(false);
assertThat(processFooCalled).isFalse();
}
class TestableSubject extends Subject {
#Override
protected void processFoo(boolean b) {
processFooCalled = true;
}
}
}
Give it a whirl. Hope it helps!
You could use a counter variable in your class and increment it whenever the method is called, or use a print statement. If you don't have access to the processFoo method, a simple approach would be to do this at the time that processFoo is called in another method, if that's the only place where it can possibly be called.
For example:
public static int processFooCalls = 0;
// ...
public void example (boolean foo) {
if (foo) {
processFoo(foo);
processFooCalls += 1;
// and/or
System.out.println("processFoo method was called");
}
// ...
}
public static void main (String[] args) {
// main routine here...
System.out.println("'processFoo' was called " + processFooCalls + " times.");
}
If processFoo can be called elsewhere, and you need to consider this possibility as well, then you'll need to have access to the processFoo code in order to do this, e.g.:
void processFoo( boolean b ) {
// increment number of times processFoo was called here, and/or print, as follows
processFooCalls += 1;
System.out.println("called processFoo method!");
/* some functionality */
}
Looking at the JMockit documentation, you will need the following tools:
Static Mocking: http://jmockit.github.io/tutorial/BehaviorBasedTesting.html#staticPartial
Invocation Counts: http://jmockit.github.io/tutorial/BehaviorBasedTesting.html#constraints
Combining the two in a test (my syntax may be a little off since I'm more accustomed to Mockito, but the concept should hold):
#Test
public void someTestMethod(#Mocked({"processFoo"}) final ExampleClass exampleclass)
{
new Expectations() {{
exampleclass.processFoo(); times = 1;
}};
exampleclass.example(true);
}
This should mock the processFoo method, leaving everything else intact, and checks to make sure it is called exactly once.
Don't consider doing any kind of partial mocking for this, all you're doing in that case is ensuring that if you want to refactor your code your tests will fail. There is a mantra in unit testing - "never test private methods".
What you should be doing is testing that the method you call conforms to the behaviour you want to see. In this case what happens when foo is true is what's important, not that it calls processFoo. So if foo is true you want to be testing that the action processFoo carries out is true and nothing else.

How to preserve group order in TestNG

I have two classes that each implement something differently but the tests are the same for both. Each class does some things that would affect the other class if they run in parallel, so they can't run in parallel. (that's the rationale behind the code below)
If you run the class Both, see below, in Eclipse, as a TestNG test, one would expect it to run tests test1 and test2 of class ClassAAA first and then the same test methods for ClassBBB, because ClassBBB's group annotations specify that it depends on ClassAAA's annotation.
However, what you find out is that, seemingly, TestNG has a different way of looking at it, and, "seemingly", it ignores the group order and runs the tests of the two clases in parallel.
class Both {
#Test(groups={"base"})
public static abstract class BothBase {
#Test public void test1() { System.out.println("test1"+name()); }
#Test public void test2() { System.out.println("test2"+name()); }
protected String name() {
String s = getClass().getName();
s = s.substring( 1 + s.lastIndexOf("$"));
return " - " + s;
}
}
#Test(groups={"gr1"})
public static class ClassAAA extends BothBase { }
#Test(groups={"gr2"},dependsOnGroups={"gr1"})
public static class ClassBBB extends BothBase { }
}
The output is:
test1 - ClassAAA
test1 - ClassBBB
test2 - ClassAAA
test2 - ClassBBB
One way, which i don't like, to try to "force" it to honor the desired group order, is to add a dummy test method to the leaf classes, as follows:
#Test(groups={"gr1"})
public static class ClassAAA extends BothBase {
#Test public void dummyTestMustBeInAllLeavesToEnforceGroupOrder() {
System.out.println("dummyTestMustBeInAllLeavesToEnforceGroupOrder"+name());
}
}
#Test(groups={"gr2"},dependsOnGroups={"gr1"})
public static class ClassBBB extends BothBase {
#Test public void dummyTestMustBeInAllLeavesToEnforceGroupOrder() {
System.out.println("dummyTestMustBeInAllLeavesToEnforceGroupOrder"+name());
}
}
This still doesn't completely do what one would expect. The output is:
test1 - ClassAAA
test2 - ClassAAA
test2 - ClassBBB
dummyTestMustBeInAllLeavesToEnforceGroupOrder - ClassAAA
test1 - ClassBBB
dummyTestMustBeInAllLeavesToEnforceGroupOrder - ClassBBB
This means that it started running the tests of ClassBBB before finishing the tests of ClassAAA.
I don't like the fact that i have to add a dummy/unrelated method to each, to get TestNG to understand that they cannot be run in parallel. In fact, i don't care which class runs first... And, i didn't really accomplish what i wanted because they are still running in parallel.
The stupidest way to do this, which would accomplish my goal is to move the tests from the base class to each of the leaf classes - is that how you are suppose to do these things in TestNG?
Is there another way of doing that? i'm sure someone is going to suggest priorities - but again, that does not convey the true intention - i don't have any priority - just don't want them to run in parallel. Also i don't want to write XML files...
This problem is coming due to static inner classes. Try below code you will get required output
import org.testng.annotations.Test;
#Test(groups={"base"})
public abstract class BothBase {
#Test public void test1() { System.out.println("test1"+name()); }
#Test public void test2() { System.out.println("test2"+name()); }
protected String name() {
String s = getClass().getName();
s = s.substring( 1 + s.lastIndexOf("$"));
return " - " + s;
}
}
#Test(groups={"gr1"})
class ClassAAA extends BothBase { }
#Test(groups={"gr2"},dependsOnGroups={"gr1"})
class ClassBBB extends BothBase { }
Many ways
Simplest - priority
Bit harder( groups)
Check testng manual(for ex. this http://www.mkyong.com/tutorials/testng-tutorials/).

Getting data out of JUnit test class in threaded environment

I am running some JUnit tests programatically with JUnitCore, and I want to get some data out of the test class once it is finished (so #AfterClass). Here is a pseudocode example of the constraints I am working under:
public class A {
public static String testData;
public static void runTest() {
JUnitCore juc = new JUnitCore();
juc.run(B);
// This is where I would like to access testData for this
// particular run
}
public static void setTestData(String s) {
testData = s;
}
}
public class B {
// Some #Test methods and stuff omitted
#AfterClass
public static void done(String s) {
A.setTestData(someData);
}
}
My problem is that different threads might be calling runTest(), so testData might be wrong. How do I work around this? I'm so lost.
If you really need/want to go with this design, you can make testData a java.lang.ThreadLocal<String>. This will solve the multi-threading issue.

How does this code work for JUnit in JAVA?

I have the following code for JUnit testing:
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
public class JUnitHelloWorld {
protected String s;
#Before
public void setup() {
s = "HELLO WORLD";
}
#Test
public void testHelloWorldSuccess() {
s = s.toLowerCase();
assertEquals("hello world", s);
}
// will fail even if testHelloWorldSuccess is called first
#Test
public void testHelloWorldFail() {
assertEquals("hello world", s);
}
}
Now, according to the comment, why will the second method fail even if the first method is called first? isn't the first method changing the value of s to lowercase?
#Before happens before each test. This means the order you run them in does not matter as it will always perform the setup then do the test.
The tag #BeforeClass will give you the behaviour you are expecting. This runs once before any of your tests start.
JUnit does not run each test case (method with #Test) in order of your code. That is why each test case must be independent of each other.
Also setup method with #Before tag will always get run before each of your test method.
So likelihood (but not necessarily) the order of execution of your code are:
setup()
testHelloWorldSuccess()
setup()
testHelloWorldFail()
But it might also run:
setup()
testHelloWorldFail()
setup()
testHelloWorldSuccess()
for JUnit , the order of testcase execution is not fixed. It may happen that you wrote a method m2 after method m1 and while execution, m2 gets executed first. The best approach is your test case should not be based on the testcase execution order.
try #BeforeClass if you want something to be executed once for the whole class only.
For the above scenario try this:
protected String s;
private int flag ;
#BeforeClass
public beforeClass(){
flag = 0;
}
#Before
public void setup() {
s = "HELLO WORLD";
}
#Test
public void testHelloWorldSuccess() {
flag = 1;
s = s.toLowerCase();
assertEquals("hello world", s);
}
// won't fail even if testHelloWorldSuccess is called first
#Test
public void testHelloWorldFail() {
if(flag == 1)
assertEquals("hello world", s);
else
assertEquals("HELLO WORLD", s);
}

Categories

Resources