#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);
}
}
Related
I am trying to find the way to test RichFilter function just like RichMappFunction like present here : RichMapFunction Testing is present here......Searched through internet and find nothing...Please help...
public class Person{
public String name;
public Int age;
}
public class OCRKafkaFilter extends RichFilterFunction<Person> {
#Override
public boolean filter(Person person) {
return person.age>21;
}
}
How can we write a test case for this rich filter function for stateful operators ...
You can up a test harness for a filter function doing something like this:
private OCRKafkaFilter function;
private OneInputStreamOperatorTestHarness<Person, Person> harness;
#BeforeEach
void setUpHarness() throws Exception {
function = new OCRKafkaFilter();
StreamFilter<Person> operator = new StreamFilter<>(function);
harness = new OneInputStreamOperatorTestHarness<>(operator);
harness.open();
}
In the example you gave, the RichFilterFunction isn't stateful. In that case you can write tests like this:
public class FilterFunctionTest {
#Test
public void testFilter() {
OCRKafkaFilter filter = new OCRKafkaFilter();
Person person21 = new Person(21);
Person person22 = new Person(22);
assertEquals(false, filter.filter(person21));
assertEquals(true, filter.filter(person22));
}
}
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);
}
}
I have a constructor that calls a method, like this:
public Foo(boolean runExtraStuff) {
if (runExtraStuff){
doExtraStuff();
}
}
The doExtraStuff() method is running some additional commands that are not easily mocked themselves (things like database checks to initialize some variables). Perhaps it would be better for the constructor to not do this, but this is the code I have to work with at the moment.
I would like to create a unit test to make sure that doExtraStuff() is called when the boolean runExtraStuff is true and does not run when the boolean is false. I am using JMockit.
However, I'm not sure how to make this happen. Normally I would use a Verifications on a mocked object, but since I am testing the constructor, I can't use a mocked object in this way. So how can I verify that a method within a constructor was called?
It's easy enough, even if it requires partial mocking:
#Test
public void runsSetupWhenRequestedOnFooInitialization()
{
// Partially mocks the class under test:
new Expectations(Foo.class) {};
final Foo foo = new Foo(true);
// Assuming "setup" is not private (if it is, use Deencapsulation.invoke):
new Verifications() {{ foo.setup(); }};
}
#Test
public void doesNotRunSetupWhenNotRequestedOnFooInitialization()
{
new Expectations(Foo.class) {};
final Foo foo = new Foo(false);
new Verifications() {{ foo.setup(); times = 0; }};
}
Of course, it would probably be better to avoid mocking in a case like this; instead, the test should check the state of the object through getters or other available methods, if at all possible.
Well, the straightforward answer doesn't use JMockit at all..
in src/main/java/example..
package example;
public class Foo {
private boolean setupRan = false;
public Foo(boolean runSetup) {
if (runSetup) setup();
}
public void setup() {
setupRan = true;
}
public boolean getSetupRan() {
return setupRan;
}
}
in src/test/java/example..
package example;
import static org.assertj.core.api.Assertions.*;
import org.junit.Test;
public class FooTest {
private Foo testSubject;
#Test
public void should_run_setup() {
testSubject = new Foo(true);
assertThat(testSubject.getSetupRan()).isTrue();
}
#Test
public void should_not_run_setup() {
testSubject = new Foo(false);
assertThat(testSubject.getSetupRan()).isFalse();
}
}
I'll go out on a limb and guess that you are interested in a partial mock here:
in src/main/java/example..
package example;
public class Foo1 {
public Foo1(boolean runSetup) {
if (runSetup) setup();
}
public void setup() {
System.out.println("in setup()");
}
}
in src/test/java/example..
package example;
import static org.assertj.core.api.Assertions.*;
import mockit.Expectations;
import mockit.Mocked;
import org.junit.Test;
public class Foo1Test {
// hateful partial mocking of test subject!
#Mocked({"setup()"})
private Foo1 testSubject;
#Test
public void should_run_setup() {
new Expectations() {{
testSubject.setup(); // setup() is called
}};
testSubject = new Foo1(true);
}
#Test
public void should_not_run_setup() {
new Expectations() {{
testSubject.setup(); times = 0;
}};
testSubject = new Foo1(false);
}
}
EDIT 1: Note that you won't see the println output since the method was mocked.
EDIT 2: Set expectations for invocations of testSubject.setup() to times = 0 in second test
I am trying to set up some parameterized test suites, unfortunately without any luck so far.
I have two set of parameters, and I would like to run multiple test cases (they are in different classes) with all possible combinations. I tried to do it with JUnit4, but I am unable to set it up correctly. This would be my basic idea:
TestSuite1.class sets up one set of parameters, then it starts TestSuite2.class.
TestSuite2.class sets up the second set of parameters, then it starts the actual test(s) that will use both parameters.
Meanwhile it seems it is not possible to set up both Suite.class and Parameterized.class in the RunWith annotation at the same time (according to google, Parameterized extends Suite, I get usually "no runnable method found" message if I use.)
This is how my code looks like basically:
TestSuite1.class:
#RunWith(Parameterized.class)
#Parameterized.SuiteClasses({TestSuite2.class})
//I have tried with #RunWith(Suite.class) and
//#Suite.SuiteClasses({TestSuite2.class}) annotations also - all combinations
public class TestSuite1{
public TestSuite1(int number) {
Params.first = number;
}
#Parameters
public static Collection<Object[]> parameters(){
Object[][] data = new Object[][] { { 1 }, { 2 }, { 3 }, { 4 } };
return Arrays.asList(data);
}
}
TestSuite2.class looks the same as TestSuite1.class, except that I have added TestCase1.class to the suite instead of TestSuite2, and that it sets another variable in Params.
TestCase1.class:
public class TestCase1 {
#Test
public void test1(){
System.out.println("first: "+Params.first+" second: "+Params.second);
Assert.assertTrue(true);
}
}
I am open to all ideas - even with TestNG for example. I have tried it also (although today was the first time I saw it), but as I noticed the suites are a bit different than in JUnit. I would prefer not to set up XML files before testing, I would like to solve all set up programmatically.
Is what I am trying to achieve possible with any framework?
Update: With TestNG I have the following code:
Start.class:
public class Start {
public static void main(String[] args){
TestListenerAdapter tla = new TestListenerAdapter();
TestNG testng = new TestNG();
testng.setTestClasses(new Class[] { FirstTest.class, SecondTest.class });
testng.addListener(tla);
testng.run();
}
}
Params.class:
public class Params {
#DataProvider(name = "param")
public static Object[][] createData() {
Object[][] data = new Object[][] { { 1 }, { 2}, { 3}, { 4} };
return data;
}
}
FirstTest.class:
public class FirstTest {
#Test(dataProvider = "param", dataProviderClass = Params.class)
public static void printIt(int number){
System.out.println("FirstTest: "+number);
}
}
SecondTest.class is the same as FirstTest.class. If I run this, it runs FirstTest 4 times, then it runs SecondTest 4 times. I would like to run FirstTest one time, and SecondTest one time also with the first set of parameters. Then I would like to run FirstTest and SecondTest one time, with the second set of parameters, etc.
I have tried to set setPreserveOrder(true), and tried all setParallel options also. On this way however the results are in kind of random order.
(It would be some selenium test. I am aware that tests should not depend on each other, but still it would be my desired way for this)
Although Parameterized extends Suite, it behaves totally different - in disrespect of the Liskov substitution principle. This is because normally the constructor Suite(Class<?>, RunnerBuilder) processes the #SuiteClasses annotation. But Parameterized(Class<?>) replaces this behaviour with a processing of #Parameters.
If you want to combine the behaviour of Suite and Parameterized you have to look outside of JUnit 4. E.g. you could implement your own Runner like Adam Hawkes already mentioned in another post here.
I did the same by myself and cobbled a library together that provides you with a ParameterizedSuite Runner: https://github.com/PeterWippermann/parameterized-suite
A parameterized test suite looks like this:
#RunWith(ParameterizedSuite.class)
#SuiteClasses({OneTest.class, TwoTest.class})
public class MyParameterizedTestSuite {
#Parameters(name = "Parameters are {0} and {1}")
public static Object[] params() {
return new Object[][] {{'A',1}, {'B',2}, {'C',3}};
}
So basicly as far as I understand, what you want to do is to run a test with set of sets of parameters. That is possible with JUnit and that is why method annotated with #Parameters returns a Collection of arrays (in general a set of sets).
Look at this example:
import static org.junit.runners.Parameterized.Parameters;
#RunWith(Parameterized.class)
public class TestCase1 {
public TestCase1(int first, int second) {
Params.first = first;
Params.second = second;
}
#Parameters
public static Collection<Object[]> parameters(){
Object[][] data = new Object[][] { { 1, 11 }, { 2, 22 }, { 3, 33 }, { 4, 44 } };
return Arrays.asList(data);
}
#Test
public void test1(){
System.out.println("first: "+Params.first+" second: "+Params.second);
Assert.assertTrue(true);
}
}
Edit:
If you want to share parameters between multiple test you could use an abstraction in your test cases.
public class AbstractParametrizedTest {
public AbstractParametrizedTest(int first, int second) {
Params.first = first;
Params.second = second;
}
#Parameterized.Parameters
public static Collection<Object[]> parameters(){
Object[][] data = new Object[][] { { 1, 11 }, { 2, 22 }, { 3, 33 }, { 4, 44 } };
return Arrays.asList(data);
}
}
#RunWith(Parameterized.class)
public class TestCase1 extends AbstractParametrizedTest {
public TestCase1(int first, int second) {
super(first, second);
}
...
}
However the best way to do it i think, would be to use TestNGs data providers. Take a look at example at section 5.6.2 and usage of static data providers
http://testng.org/doc/documentation-main.html
To achieve the goal of executing all test cases with the same parameters in sequential order, you would need a different Runner as this behavior is held in that class. You're in luck, as this is available in the JUnit Toolbox Project with the ParallelParameterized class!
Here some other suggest that seems to be much more flexible: #RunWith(Enclosed.class)
In short:
Instead of #Suite.SuiteClasses(...), just use #RunWith(Enclosed.class) and extend your Test Classes
#RunWith(Enclosed.class)
public class FastTest {
public static class Test1FirstAppInit extends AppInitTest { }
public static class Test2Download extends DownloadTest{ }
public static class Test3OtherTest extends OtherTest { }
}
Now with Parameterized:
#RunWith(Enclosed.class)
public class FastTest {
private static Iterable<? extends Object> mAllLocale = Arrays.asList(Locale.ENGLISH, Locale.GERMAN);
private static Iterable<? extends Object> mSingleLocale = Arrays.asList(Locale.ENGLISH);
/*
Run test class for all Locale
*/
#RunWith(Parameterized.class)
public static class Test1FirstAppInit extends AppInitTest {
#Parameterized.Parameter
public Locale mLocale;
#Parameterized.Parameters
public static Iterable<? extends Object> data() {
return mAllLocale;
}
#Override
public Locale getLocale() {
return mLocale;
}
#Override
public void test001ResetAll {
assumeTrue(false); // skip test completedly
}
#Override
public void test002ClearAppData() {
// replace existing test
if (getLocale() != Locale.ENGLISH) {
/*
should run only on first Locale
skip test on following Parameter runs
*/
assumeTrue(false); // skip test
}
else {
super.test000ClearAppData();
}
}
}
/*
Run test class only for one Locale
*/
#RunWith(Parameterized.class)
public static class Test2Download extends DownloadTest{
#Parameterized.Parameter
public Locale mLocale;
#Parameterized.Parameters
public static Iterable<? extends Object> data(){
return mSingleLocale;
}
#Override
public Locale getLocale() {
return mLocale;
}
#Override
public void test900Delete() {
assumeTrue(false); // skip test
}
}
/*
Test not Parameterized
*/
public static class Test3OtherTest extends OtherTest { }
}
Your Test Classes for Parameterized tests look like this:
#RunWith(AndroidJUnit4.class)
#LargeTest
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class DownloadTest {
public Locale getLocale() {
// will be overwritten in #RunWith(Enclosed.class)
// but we are still able to run test class separatedly
return Locale.ENGLISH;
}
#Test
public void test900Delete() {
....
}
....
}
Matches exactly what I was searching for. I can create different Test scenarios (full test, fast test,...). Just create different #RunWith(Enclosed.class) classes and extend the tests that you want to include.
Only side point seems to be that Enclosed.class does not care about sort order (if important to you).
I solved it by replacing Enclosed:
public class SortedEnclosed extends Suite {
public SortedEnclosed(Class<?> klass, RunnerBuilder builder) throws Throwable {
super(builder, klass, filterAbstractClasses(klass.getClasses()));
}
protected static Class<?>[] filterAbstractClasses(final Class<?>[] classes) {
final List<Class<?>> filteredList= new ArrayList<Class<?>>(classes.length);
for (final Class<?> clazz : classes) {
if (!Modifier.isAbstract(clazz.getModifiers())) {
filteredList.add(clazz);
}
}
// this is new (there may be better way with own "#FixClassOrder"...):
Collections.sort(filteredList, new Comparator<Class<?>>() {
#Override
public int compare(Class<?> o1, Class<?> o2) {
return o1.getSimpleName().compareTo(o2.getSimpleName());
}
});
//
return filteredList.toArray(new Class<?>[filteredList.size()]);
}
}
And then use #RunWith(SortedEnclosed.class)
In junit4 I want to execute specific test methods from different classes i.e want create a test suite with specific test methods from different classes.
Lets say I have 2 classes:
public class Test_Login {
#Test
public void test_Login_001(){
System.out.println("test_Login_001");
}
#Test
public void test_Login_002(){
System.out.println("test_Login_002");
}
#Test
public void test_Login_003(){
System.out.println("test_Login_003");
}
}
public class Logout {
#Test
public void test_Logout_001(){
System.out.println("test_Logout_001");
}
#Test
public void test_Logout_002(){
System.out.println("test_Logout_002");
}
#Test
public void test_Logout_003(){
System.out.println("test_Logout_003");
}
}
From the above classes I want to execute test methods test_Login_001 , test_Login_003 , test_Logout_002 only.
How this can be achieved in junit4 ?
Since JUnit 4.8 introduced Categories there exists a clean solution, create a TestSuite:
#RunWith(Categories.class)
#IncludeCategory(MustHaveTests.class)
#SuiteClasses( { Test_Login.class, Test_Logout.class })
public class MustHaveTestsTestSuite {
public interface MustHaveTests { /* category marker */ }
}
And add the #Category(MustHaveTests.class) above every test you would like to run with the TestSuite, e.g.:
#Category(MustHaveTests.class)
#Test
public void test_Login_001(){
System.out.println("test_Login_001");
}
When running the TestSuite only the MustHaveTests-"tagged" tests will be executed. More Details on #Category: https://github.com/junit-team/junit4/wiki/categories
You need to create an org.junit.runner.Request and pass it to the JunitCore runner, or actually to any Runner.
JUnitCore junitRunner = new JUnitCore();
Request request = Request.method(Logout.class, "test_Logout_002");
Result result = junitRunner.run(request);
I actually created an Annotation and can search for methods with those annotations and dynamically create Request and run them
public class TestsSuite {
public static void main(String[] args) throws Exception {
Class annotation = MyTestAnnotation.class;
JUnitCore junitRunner = new JUnitCore();
Class testClass = Test_Login.class;
Method[] methods = testClass.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(annotation)) {
if (method.isAnnotationPresent(org.junit.Test.class)) {
Request request = Request.method(testClass, method.getName());
Result result = junitRunner.run(request);
System.out.println(result.wasSuccessful());
}
}
}
}
}
This might not be the slickest implementation, but I solved a similar problem by created a new #SuiteMethods annotation as follows:
SuiteMethods.java
#Retention(RUNTIME)
#Target(TYPE)
public #interface SuiteMethods {
String[] value() default {""};
}
FilteredSuite.java
public class FilteredSuite extends Categories {
private static String[] TEST_METHODS_TO_RUN = {""}; // default behavior is to run all methods
private static Class<?> extractMethodNamesFromAnnotation(Class<?> clazz) {
SuiteMethods methodsAnnotation = clazz.getAnnotation(SuiteMethods.class);
if (methodsAnnotation != null) {
// if our MethodsAnnotation was specified, use it's value as our methods filter
TEST_METHODS_TO_RUN = methodsAnnotation.value();
}
return clazz;
}
public static Filter getCustomFilter() {
Filter f = new Filter() {
#Override
public boolean shouldRun(Description desc) {
String methodName = desc.getMethodName();
for (String subString : TEST_METHODS_TO_RUN) {
if (methodName == null || methodName.contains(subString)) {
return true;
}
}
return false;
}
#Override
public String describe() {
return null;
}
};
return f;
}
public FilteredSuite(Class<?> arg0, RunnerBuilder arg1) throws InitializationError {
super(extractMethodNamesFromAnnotation(arg0), arg1);
}
#Override
public void filter(Filter arg0) throws NoTestsRemainException {
// At test suite startup, JUnit framework calls this method to install CategoryFilter.
// Throw away the given filter and install our own method name filter
super.filter(getCustomFilter());
}
}
A Usage Example
#RunWith(FilteredSuite.class)
#SuiteClasses({
GroupRestTest.class,
ScenarioRestTest.class
})
#SuiteMethods({
"testReadOnlyFlag",
"testSheetWriteData",
"testAddScenarioMeta"
})
public class SubsetTestSuite {
}