JUnit test methods selection at runtime - java

I have one TestCase class, whcih has 5 test methods. I can directly execute this class, then all the test methods will be executed. This is fine.
Suppose If I want to execute few test methods(but not all) and those methods will be decided based on certain condition at run time, what is the solution..?
To be more clear,
I have a TestCase class "MyTestCase"
public class MyTestCase extends TestCase
{
#Test
public void test1()
{
....
}
#Test
public void test2()
{
....
}
#Test
public void test3()
{
....
}
#Test
public void test4()
{
....
}
#Test
public void test5()
{
....
}
}
If I run this class, all the tests will be executed.
But my requirement is: I don't want all methods to be executed always. Sometimes 2 methods or 3 methods or 4 methods etc....
I have an XML file, which decides what test methods have to be executed.
Whatever is there in the XML file, only those test methods should be executed.
(I have a class, which reads the XML file to get the test method names.)
Is there any way to control no of test methods to be executed in a TestCase class at run time....?
I think I have to use TestSuite class. But I am not sure on how to use it exactly.
Can any one help in solving this problem...?
Thanks in advance,
Sunil

You can use a custom TestRunner to execute this.
public class SelectiveJunitRunner extends BlockJUnit4ClassRunner {
public SelectiveJunitRunner(Class<?> klass) throws InitializationError {
super(klass);
}
#Override
protected List<FrameworkMethod> computeTestMethods() {
//Inject ignore List
List<String> ignoreList = Arrays.asList("test2","test4");
List<FrameworkMethod> computeTestMethods = super.computeTestMethods();
List<FrameworkMethod> filteredList = new ArrayList<>();
for (FrameworkMethod frameworkMethod : computeTestMethods) {
if (!ignoreList.contains(frameworkMethod.getName()))
filteredList.add(frameworkMethod);
}
return filteredList;
}
}
Junit Test case
#RunWith(SelectiveJunitRunner.class)
public class SelectiveTest {
#Test
public void test1() {
System.out.println("1");
}
#Test
public void test2() {
System.out.println("2");
}
#Test
public void test3() {
System.out.println("3");
}
#Test
public void test4() {
System.out.println("4");
}
}

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
}
}

Mockito mocking same named method with similar signatures

I have a class, say SimpleClass, that has two functions with the same name and the same number of parameters but different parameter types. Now I assume mocking their return values should be as using two when statements with the appropriate matchers but instead when I attempt that I get the following error:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here:
-> at mocks.MockTest.whenMethodsHaveSimilarSignatures(MockTest.java:28)
-> at mocks.MockTest.whenMethodsHaveSimilarSignatures(MockTest.java:28)
Here's a sample of what I'm attempting:
public class SimpleClass {
public boolean doWork(String value, String name) {
return false;
}
public boolean doWork(Integer value, String name) {
return true;
}
}
#RunWith(MockitoJUnitRunner.class)
public class MockTest {
private SimpleClass thing;
#Before
public void setup() {
thing = new SimpleClass();
}
#Test
public void whenMethodsHaveSimilarSignatures() {
when(thing.doWork(anyString(), anyString())).thenReturn(true);
when(thing.doWork(any(Integer.class), anyString())).thenReturn(false);
assertThat(thing.doWork("one", "name")).isTrue();
assertThat(thing.doWork(1, "name")).isFalse();
}
}
While I'm not a wizard at Mockito I've been using it for a while and never encountered this issue. Thoughts? I'm using Mockito-Core v2.2.9
You should not use any(Object.class) while stubbing overloaded methods because both String and Integer are child classes of Object, so specify the particular arguments during stubbing.You can also use ArgumentMatchers
when(thing.doWork(ArgumentMatchers.anyString(), ArgumentMatchers.anyString())).thenReturn(true);
when(thing.doWork(ArgumentMatchers.any(Integer.class), anyString())).thenReturn(false);
And also you are not mocking the SimpleClass
#RunWith(MockitoJUnitRunner.class)
public class MockTest {
private SimpleClass thing = Mockito.mock(SimpleClass.Class);
#Before
public void setup() {
MockitoAnnotations.initMocks(this); // need to enable these annotations programmatically
}
#Test
public void whenMethodsHaveSimilarSignatures() {
when(thing.doWork(anyString(), anyString())).thenReturn(true);
when(thing.doWork(any(Integer.class), anyString())).thenReturn(false);
//or
when(thing.doWork(ArgumentMatchers.anyString(), ArgumentMatchers.anyString())).thenReturn(true);
when(thing.doWork(ArgumentMatchers.any(Integer.class), anyString())).thenReturn(false);
assertThat(thing.doWork("one", "name")).isTrue();
assertThat(thing.doWork(1, "name")).isFalse();
}
}

Mockito: verifying method call from internal anonymous class

I have a class under test which contains a method which has an inner anonymous class. One of the methods in the anonymous class calls a method from the class under test, but Mockito doesn't seem to realize this.
public class ClassUnderTest {
Dependency dependency;
public ClassUnderTest(Dependency d) {
dependency = d;
}
public void method() {
dependency.returnsObservable().observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io()).subscribe(new Observer<SupportClass> {
/* Other methods omitted */
public void onComplete() {
outerMethod();
})
}
public void outerMethod() {
blah;
}
}
My test code:
public class TestClass {
ClassUnderTest underTest;
Dependency dependency;
#Before
public void setUp() throws Exception {
dependency = Mockito.mock(Dependency.class);
underTest = Mockito.spy(new ClassUnderTest(dependency));
}
#Test
public void method() throws
Mockito.when(dependency.returnObservable()).thenReturn(Observable.just(new SupportClass());
Mockito.doNothing().when(underTest).outerMethod();
underTest.method();
Mockito.verify(underTest).outerMethod();
}
}
For some reason that I can't seem to figure out, Mockito can't detect that outerMethod() is being called, even though I have manually verified by stepping through line by line in the debugger. I have also verified that the call to the dependency object returns the proper observable with the correct content, and the onComplete() and outerMethod() methods do get called. I'm just confused why Mockito doesn't detect it as such.
This is the error that it spits out:
Wanted but not invoked:
classUnderTest.outerMethod();
-> at (file and line number)
However, there was exactly 1 interaction with this mock:
classUnderTest.method();
-> at (file and line number)
Is there anything obvious I'm missing?
You're changing between schedulers so it can cause some issues when testing (your code may reach the verify method before the actual method is invoked
Check this article explaining how to test asynchronous code with RxJava and Mockito
TL;DR
Add a TestRule that set all schedulers to trampoline so it behaves synchronously:
public class TrampolineSchedulerRule implements TestRule {
#Override
public Statement apply(final Statement base, Description d) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
RxJavaPlugins.setIoSchedulerHandler(
scheduler -> Schedulers.trampoline());
RxJavaPlugins.setComputationSchedulerHandler(
scheduler -> Schedulers.trampoline());
RxJavaPlugins.setNewThreadSchedulerHandler(
scheduler -> Schedulers.trampoline());
RxAndroidPlugins.setInitMainThreadSchedulerHandler(
scheduler -> Schedulers.trampoline());
try {
base.evaluate();
} finally {
RxJavaPlugins.reset();
RxAndroidPlugins.reset();
}
}
};
}
}

How can I make sure my JUnit test method's specific cleanup always runs?

I have a JUnit test class that has two test methods:
#Test
public void test1() {
// Setup: Create foo1.m
// Exercise
// Tear Down: Delete foo1.m
}
#Test
public void test2() {
// Setup: Create foo2.m
// Exercise
// Tear Down: Delete foo2.m
}
For each method, I would like to make sure that, if the Exercise section fails for any reason, the Tear Down will still run. Note that the Setup and Tear Down code for both test methods are different, so I don't think I can use JUnit's #Before and #After annotations to do what I want.
I could put TRY-CATCH blocks into each test method:
#Test
public void test2() {
// Setup: Create foo2.m
try {
// Exercise
} finally {
// Tear Down: Delete foo2.m
}
}
but that seems ugly. Is there a way to make sure the test-method-specific tear down code in each test method is executed, without using a TRY-CATCH block?
If the setup and teardown are different, you are essentially cramming two different test fixtures into a single file. The sensible answer is to put them in separate files and use the normal annotations. If they have anything in common separate that out into a common abstract class.
Adding multiple setups in the same file can easily result in a situation where it's not clear which instance members are used in which tests, so that maintaining the tests becomes a lot harder than it needs to be.
Update:
I found a better solution, so I include here, the original answer can be found below. I think JUnit 4 rules can be used here:
class PrepareFile implements org.junit.rules.TestRule {
#Retention(RetentionPolicy.RUNTIME)
public #interface FileName {
String value() default "";
}
#Override
public Statement apply(final Statement statement, final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
String fileName = description.getAnnotation(FileName.class).value();
File file = new File(fileName);
try {
file.createNewFile();
statement.evaluate();
} finally {
file.delete();
}
}
};
}
}
Using it in the test:
#Rule
public PrepareFile prepareFile = new PrepareFile();
#Test
#PrepareFile.FileName("foo1.m")
public void test1() {
// Exercise
}
#Test
#PrepareFile.FileName("foo2.m")
public void test2() {
// Exercise
}
Here comes my original answer:
You may try to use the #BeforeClass and #AfterClass annotations.
#BeforeClass
public static void setUp() {
// Setup1: Create foo1.m
// Setup2: Create foo2.m
}
#AfterClass
public static void tearDown() {
// Tear Down1: Delete foo1.m
// Tear Down2: Delete foo2.m
}
#Test
public void test1() {
// Exercise
}
#Test
public void test2() {
// Exercise
}
This way you can setup and tear down all test cases once and the framework ensures that teadDown() is called in case of errors as well.

How can I reflectively access the test method to run after a call to #Before setup()?

We have lots of selenium tests running through junit, and they all have a few steps which need to run before the actual tests. For this we have a parent TestCase class which has some #Before and #After methods in it.
Now, due to a new feature of our site I would like to parameterise part of this set up, I'd like to create a new annotation to put on some tests to indicate to the setup() method that the setup is slightly different, whilst allowing the others to use the default. So, is it possible to reflectively access the test method about to be run in an #Before method?
eg.
class SomeTest extends MyTestCase {
#Test
#Flavour(Red.class)
public void testRedFlavouredHomepage() {
testHomepage();
}
#Test
public void testBlueFlavouredHomepage() { // assuming Blue is my default flavour
testHomepage();
}
public void testHomepage() {
// test some stuff
}
}
You can do this using #Rule (with the later versions of JUnit >= 4.9). If you have a class which implements TestRule, specifically apply(), you can do extra things before your test gets run. The Description is passed to the apply method, which contains the annotations on your method:
Using #Deprecated as an example:
public class ExtraSetupTest {
#Rule
public TestRule moreSetup = new TestRule() {
public Statement apply(Statement base, Description description) {
return statement(base, description);
}
private Statement statement(final Statement base,
final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
if (description.getAnnotation(Deprecated.class) != null) {
System.out.println("more setup here");
}
base.evaluate();
}
};
}
};
#Test
public void noExtraSetup() {
System.out.println("noExtraSetup");
}
#Test
#Deprecated
public void withExtraSetup() {
System.out.println("withExtraSetup");
}
}
This produces as output:
noExtraSetup
more setup here
withExtraSetup
I'd rather suggest to use different test classes for those 2 methods.
class MyTestCase {
#Before
public void setUp() {
/* Default setup */
}
public void testHomepage() {
// test some stuff
}
}
class MyRedTestCase extends MyTestCase {
#Before
public void setUp() {
super.setUp();
/* Red setup */
}
}
And then you can put your tests into 2 different classes extending from MyTestCase and MyRedTestCase respectively.
class BlueTest extends MyTestCase {
#Test
public void testBlueFlavouredHomepage() { // assuming Blue is my default flavour
testHomepage();
}
}
class RedTest extends MyRedTestCase {
#Test
public void testRedFlavouredHomepage() {
testHomepage();
}
}
You can do it another way as well, without introducing new classes. Declare an absract (or concrete with the default value) method in your parent class.
class MyTestCase {
protected abstract Flour getFlour();
}
And your child class will look like this
class SomeTest extends MyTestCase {
private Flour flour;
#Test
public void testRedFlavouredHomepage() {
flour = Flour.RED;
testHomepage();
}
#Test
public void testBlueFlavouredHomepage() { // assuming Blue is my default flavour
flour = Flour.BLUE;
testHomepage();
}
public void testHomepage() {
// test some stuff
}
protected abstract Flour getFlour() {
return flour;
}
}
I'd say the 1st solution is "cleaner"; even though you have to create additional classes, you don't include logic of different types in one class (like in the anti-pattern God object).

Categories

Resources