Passing parameter to #Before setup in jUnit test [duplicate] - java

This question already has answers here:
Is it possible to use different #Before #After for each test case in JUnit?
(2 answers)
Closed 8 years ago.
Is there any way to avoid calling populateRandomData() method at the begining of each test without having a fixed parameter 100. I need to call the same method to setup data before execution of each test but I need to change the number of test data entries e.g. 100 in each case .
public class Tester
{
#Before
public void setUp() {
populateRandomData(100)
}
#Test
public void testMethod() {
}
private void populateRandomData(n){
//n times insert random data in table.
}
}

You can create Parameterized JUnit Test which allows you to add number of parameters you want to pass in unit test case. Have a look at example tutorial Create Parameterized Test Case.
OR
#Rule, using this annotations on your test methods to parameterize the execution of your rules makes it even more useful. Taken from JUnit 4.7 #Rules
EDIT :
Example of Using #Rule :
Below is the class which allows you to initialize different value of num variable which will be used in test method :
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class Test1 implements TestRule {
private final int num;
public Test1(int num) {
this.num = num;
}
public int getNum() {
return num;
}
public class Test1Statement extends Statement {
private final Statement statement;
public Test1Statement(Statement statement, int num) {
this.statement = statement;
}
#Override
public void evaluate() throws Throwable {
statement.evaluate();
}
}
#Override
public Statement apply(Statement statement, Description description) {
return new Test1Statement(statement, num);
}
}
The class below is the actual test case class. It contains JUnit test cases & set value of num variable in test method.
import org.junit.Rule;
import org.junit.Test;
public class RuleNumberTester {
#Rule
public Test1 test = null;
#Rule
public Test1 test1 = null;
#Test
public void num1Test() {
test = new Test1(111);
System.out.println("Num 1 : " + test.getNum());
}
#Test
public void num2Test() {
test1 = new Test1(222);
System.out.println("Num 2 : " + test1.getNum());
}
}
Output :
Test cases are executed successfully & shows the values of num variable which was initialized in test methods on console.
Num 1 : 111
Num 2 : 222

I suppose you could use a #Rule to ensure populateRandomData() is called each time with the correct parameters.
However, this gets ugly quickly since you then need to maintain a list of test method names.
private static final Map<String, Integer> dataCounts = new HashMap<>();
static {
// list (or otherwise obtain) counts here
dataCounts.put("testMethod", 100);
}
#Rule
public TestWatcher watcher = new TestWatcher() {
#Override
protected void starting(Description description) {
Integer count = dataCounts.get(description.getMethodName());
assertNotNull(count);
populateRandomData(count.intValue());
};
};

Related

Error when using the same string in different tests

I have the following scenario:
I perform several tests (#Test) and tests in Cucumber, in Selenium Webdriver, Java.
The tests are going well. However, I want to leave a string stored in one #Test (public void) in another #Test (public void). I cannot.
Could anyone help?
First test:
#Test
public void testDocuments() {
OneClass oneClass = new OneClass();
oneClass.one();
oneClass.two();
}
Second test:
#Test
public void testDocuments() {
OneClass oneClass = new OneClass();
oneClass.one();
oneClass.two();
}
Method one
public String one() {
if (this.cnpj == null) {
this.cnpj = add.cnpj(false);
} else {
}
return this.cnpj;
}
Both tests I want you to use the same generated string !!!!
I look forward and thanks in advance!
I'm not sure what your method one() does, but assuming you want to use the same value for two different tests, why not just do this:
OneClass oneClass = new OneClass();
String yourGeneratedString = oneClass.one();
// First test
#Test
public void testDocuments() {
yourFunction(yourGeneratedString);
}
// Second test
#Test
public void testDocuments2() {
yourOtherFunction(yourGeneratedString);
}
If I understand correctly, you need this.cnpj value to be available within the second test?
Each time you do new OneClass() , it creates a new instance of it.
So you can do one of the following:
Use singleton instance of OneClass
Make cnpj a static field within OneClass
If I understand it right, you want to share data from one test to second one. If you user testNG then you can do it this way.
import org.testng.ITestContext;
import org.testng.annotations.Test;
public class MyTest {
#Test
public void testOne(ITestContext context){
context.setAttribute("myKey", "myValue");
}
#Test
public void testTwo(ITestContext context){
String valueFromTestOne = (String) context.getAttribute("myKey");
System.out.println("My key = " + valueFromTestOne);
}
}

value of global variable is changing to null in JUnit

I wrote a simple class, in which first function's output is second function's input and second function's output is third function's input.
After that I am printing these outputs in another class which implements JUnit #Test cases.
But for call to second function's test, I'm getting 'res' value as null(which should be output of first function and passing it as input to second function). Same is the case with third function.
I'm declaring 'res' as global variable. Then why is its value changing to null instead of holding the result of first function and then of second function( for call to third function) ?
Here is the class which contains 3 functions:
package con.nc.junitexmples.Junit4Examples;
public class StringExample {
public static String firstFunction() {
String msg1 = "msg1";
return msg1;
}
public static String secondFunction(String msg1) {
String msg2 = msg1+"msg2";
return msg2;
}
public static String thirdFunction(String msg2) {
String msg3= msg2+"msg3";
return msg3;
}
}
Here is class which implements JUnit #Test cases and printing output:
package con.nc.junitexmples.Junit4Examples;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestStringExample {
String res;
#BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("\n\t\t-----JUnit cascading input Example------\n\n");
System.out.println("before class---->only once");
}
#Before
public void setUp() throws Exception {
System.out.println("\nbefore--->before each test case");
}
#Test
public void testFirstFunction(){
System.out.println("\ttest case: FIRST Function");
res = StringExample.firstFunction();
System.out.println("\t"+res);
}
#Test
public void testSecondFunction(){
System.out.println("\ttest case: SECOND Function");
res = StringExample.secondFunction(res);
System.out.println("\t"+res);
}
#Test
public void testThirdFunction(){
System.out.println("\ttest case: THIRD Function");
res = StringExample.thirdFunction(res);
System.out.println("\t"+res);
}
#After
public void tearDown() throws Exception {
System.out.println("after ---> after each test case\n\n");
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("after class--->only once");
}
}
And here is the output I'm getting:
-----JUnit cascading input Example------
before class---->only once
before--->before each test case
test case: FIRST Function
msg1
after ---> after each test case
before--->before each test case
test case: SECOND Function
**nullmsg2**
after ---> after each test case
before--->before each test case
test case: THIRD Function
**nullmsg3**
after ---> after each test case
after class--->only once
How do I pass result of first function to second as input and so on?
Each of these tests is self contained, independent and the value of res at the start of these tests methods is null.
So, that explains why you are seeing:
nullmsg2
nullmsg3
Given this question from the comments above:
how do I pass output of first function as input to second function for second test?
You could test all three calls in one test method, like so:
#Test
public void testAll() {
String res = StringExample.firstFunction();
Assert.assertEquals("msg1", res);
res = StringExample.secondFunction(res);
Assert.assertEquals("msg1msg2", res);
res = StringExample.thirdFunction(res);
Assert.assertEquals("msg1msg2msg3", res);
}
For pass the result of first function to second function:
#Test
public void testSecondFunction(){
System.out.println("\ttest case: SECOND Function");
String resFromFirstFunc = StringExample.firstFunction();
res = StringExample.secondFunction(resFromFirstFunc);
System.out.println("\t"+res);
}
But you shouldn't write the test like above example, it always passed.
You should use:
Assert.assertEquals(input,output)

JUnitParams - executing separate methods before test

#RunWith(JUnitParamsRunner.class)
public class MySimpleTest {
private MyRec rec;
private Matrix matrix;
#Before
public void createRecognizerBeforeEveryExecution() {
rec = new MyRec();
matrix = MatrixUtils.createMatrixWithValues();
}
public static Iterable<Object[]> data() {
return Arrays.asList(
new Object[]{"expectedvalue1", "input1"},
new Object[]{"expectedvalue2", "input2"}
);
}
#Test
#Parameters(method = "data")
public void test1(String output, String input) {
rec.fun1(matrix);
assertEquals(output, rec.someFunction(input));
}
public static Iterable<Object[]> data2() {
return Arrays.asList(
new Object[]{"expectedothervalue1", "input1"},
new Object[]{"expectedothervalue2", "input2"}
);
}
#Test
#Parameters(method = "data2")
public void test2(String output, String input) {
rec.fun1(matrix);
rec.fun2(matrix);
assertEquals(output, rec.someFunction(input));
}
}
I'm trying to find out what is the proper way to make this test. I'd like to use parametrized test, because it's really convenient way.
So as you can see, in every test function I call some function (fun1 and fun2). But I need to call it only once per every test (e.g. before each parametrized test execution).
Is there any way to tell JUnitParams that it should execute other function before executing all of parametrized tests?
I can't use #Before annotation, because as you can see in test1 I'm not using fun2. It think it should be executed by separate function.
Solution 1:
As fun[1|2] does not depend on internal test state, try to place their invocations inside data and data2 methods accordingly.
public static Iterable<Object[]> data() {
rec.fun1(matrix);
return Arrays.asList(
new Object[]{"expectedvalue1", "input1"},
new Object[]{"expectedvalue2", "input2"}
);
}
public static Iterable<Object[]> data2() {
rec.fun1(matrix);
rec.fun2(matrix);
return Arrays.asList(
new Object[]{"expectedvalue1", "input1"},
new Object[]{"expectedvalue2", "input2"}
);
}
Solution 2:
Spliting test cases is not a best practice. Your test are harder to maintain. Flow is far more complicated. There is also a risk your tests start depends on each other. Duplication in tests sometimes is simply better.
PS:
If you are using Strings as test method parameters it's better to pass them exactly like in 25th line of this file:
https://github.com/Pragmatists/JUnitParams/blob/master/src/test/java/junitparams/usage/SamplesOfUsageTest.java instead of special methods.
#Test
#Parameters({"AAA,1", "BBB,2"})
public void paramsInAnnotation(String p1, Integer p2) { }
I decided to use TestNG to resolve this problem (code just to show my train of thought):
import org.testng.Assert;
import org.testng.annotations.*;
import java.lang.reflect.Method;
public class TempTest {
private Integer number;
#BeforeMethod
public void init(Method m) {
number = 5;
switch(m.getName()) {
case "test2":
fun(10);
fun2(5);
break;
case "test1":
fun(10);
break;
}
}
public void fun(int value) {
number += value;
}
public void fun2(int value) {
number -= value;
}
#Test
public void test1() {
Assert.assertEquals(new Integer(15), number);
}
#Test
public void test2() {
Assert.assertEquals(new Integer(10), number);
}
#Test
public void test3() {
Assert.assertEquals(new Integer(5), number);
}
}

JUnit set up test case

I have never used JUnit before and I'm having some trouble setting up the tests. I have a Java project and a package, both named 'Project1' with one class which I'm trying to test called 'Module'. At the moment I'm just wanting to check if the values are correct.
Module class
package Project1;
//This class represents a module
public class Module {
public final static int MSC_MODULE_PASS_MARK = 50;
public final static int UG_MODULE_PASS_MARK = 40;
public final static int MSC_MODULE_LEVEL = 7;
public final static int STAGE_3_MODULE_LEVEL = 6;
private String moduleCode;
private String moduleTitle;
private int sem1Credits;
private int sem2Credits;
private int sem3Credits;
private int moduleLevel;
public Module(String code, String title, int sem1, int sem2, int sem3, int level)
{
moduleCode = code;
moduleTitle = title;
sem1Credits = sem1;
sem2Credits = sem2;
sem3Credits = sem3;
moduleLevel = level;
}
//method to return the module code
public String getCode()
{
return moduleCode;
}
//INSERT A BUNCH OF GET METHODS
}
Test case
Here is where I get lost. I'm trying to give some dummy values to test but I'm not sure how to pass the instance of Module to test.
package Project1;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class TestCase {
#BeforeClass
public static void setUpBeforeClass() throws Exception {
}
#Before
public void setUp() throws Exception {
Module csc8001 = new Module("CSC8001", "Programming and data structures", 20, 0, 0, 7);
}
#Test
public void test() {
if (csc8001.getCode() == "CSC8001") {
System.out.println("Correct");
}
else{
fail("Not yet implemented");
}
}
}
Make your Module variable an instance variable in your test class, instead of a local variable in a method. Then the #Before method will just initialize the variable, not declare it too. Then it will be in scope in any #Test method.
Incidentally, compare your string contents with String's equals method, not ==.
import static org.junit.Assert.assertEquals;
public class TestCase {
private final Module csc8001 = new Module("CSC8001", "Programming and data structures", 20, 0, 0, 7);
#Test
public void testGetCode() {
assertEquals("Some error message", "CSC8001", csc8001.getCode()) ;
}
}
Always use equals:
if (csc8001.getCode().equals("CSC8001")) {
furthermore declare csc8001 as a class member.
public class TestCase {
private Module csc8001;
and
#Before
public void setUp() throws Exception {
csc8001 = new Module("CSC8001", "Programming and data structures", 20, 0, 0, 7);
}
Make your Module an instance variable. Remember that for each separate #Test method, JUnit will create a separate instance of your test class and run all of your #Before methods on it. Though you can instantiate your system under test in the same place you declare it, it may be advantageous to keep it in #Before as you have it.
public class TestCase {
private Module csc8001;
#Before public void setUp() throws Exception {
csc8001 = new Module("CSC8001", "Programming and data structures", 20, 0, 0, 7);
}
#Test public void test() { /* ... */ }
}
You can also use assertEquals to check equality, which will automatically fail with a clear message if the parameters don't match.
#Test
public void codeShouldEqualCSC8001() {
assertEquals("CSC8001", csc8001.getCode());
}
See assertEquals and more at the org.junit.Assert documentation.
p.s. Remember that the prefix test and the name setUp are holdovers from JUnit 3, and that using JUnit4 or better (with annotations like #Before and #Test) you are free to add multiple #Before and #After methods and give all your methods unconstrained names.

In Eclipse, how do I run a JUnit test case multiple times

I have a unit test that fails sometimes and debugging it is a pain because I don't know why it sometimes fails.
Is there a way inside Eclipse that I can run a JUnit test 5 times or 50 times or something?
Thanks.
I just found the following solution which doesn't require any additional depedency (Spring is required for one of the answers you got).
Run your test with the Parameterized runner:
#RunWith(Parameterized.class)
Then add the following method to provide a number of empty parameters equals to the number of times you want to run the test:
#Parameterized.Parameters
public static List<Object[]> data() {
return Arrays.asList(new Object[10][0]);
}
This way you don't even have to write a loop. IntelliJ and eclipse also group the results of every iteration together.
Have you tried something like this?
#Test
public void runMultipleTests() {
for (int i = 0; i < 10; i++) {
myTestMethod();
}
}
There is a test decorator for this. See Junit API at
http://junit.org/apidocs/junit/extensions/RepeatedTest.html
for example
#Test
#Repeat(10)
public void FailRandomlyNeedToKnowWhy() {
....
}
Inspired on this solution:
Use #Repeat annotation like this:
public class MyTestClass {
#Rule
public RepeatRule repeatRule = new RepeatRule();
#Test
#Repeat(10)
public void testMyCode() {
//your test code goes here
}
}
You'll only need these two classes:
Repeat.java:
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention( RetentionPolicy.RUNTIME )
#Target({ METHOD, ANNOTATION_TYPE })
public #interface Repeat {
int value() default 1;
}
RepeatRule.java:
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class RepeatRule implements TestRule {
private static class RepeatStatement extends Statement {
private final Statement statement;
private final int repeat;
public RepeatStatement(Statement statement, int repeat) {
this.statement = statement;
this.repeat = repeat;
}
#Override
public void evaluate() throws Throwable {
for (int i = 0; i < repeat; i++) {
statement.evaluate();
}
}
}
#Override
public Statement apply(Statement statement, Description description) {
Statement result = statement;
Repeat repeat = description.getAnnotation(Repeat.class);
if (repeat != null) {
int times = repeat.value();
result = new RepeatStatement(statement, times);
}
return result;
}
}
2016-10-25 Edit:
In order to use this solution when using #RunWith(PowerMockRunner.class), update to Powermock 1.6.5 (which includes this patch).

Categories