2

I have developed a web base application that in some way let's the user submit a test case just by inputting values instead of writing a complete JUnit test.

The way I used till now is generating a test class for each submission and then compile it and run.

For example assume we have a class like bellow:

public class CalculatorO
{    
    public  boolean isPrime( int n )
    {
        if (n < 2) {
            return false;
        }
        int count = 0;
        for (int i = 1; i <= n; i++) {
            if (n % i == 0) {
                count++;
            }
        }
        if (count == 2) {
            return true;
        } else {
            return false;
        }
    }
}

As oracle, and another class like bellow:

public class CalculatorM0
{    
    public  boolean isPrime( int n )
    {
        if (n < 2) {
            return false;
        }
        int count = 0;
        for (int i = 1; i <= n; i++) {
            if (n * i == 0) {
                count++;
            }
        }
        if (count == 2) {
            return true;
        } else {
            return false;
        }
    }    
}

As subject of the test. Then I generate a test template as following:

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertArrayEquals;
import static org.unitils.reflectionassert.ReflectionAssert.assertReflectionEquals;
import org.junit.Test;

public class {{TestClassName}} {
  @Test
  public void {{MethodName}}() {
    int AO = {{valueA}};


    int AM = {{valueA}};

    {{OriginalClassName}} {{OriginalClassNameLower}} = new {{OriginalClassName}}();
    {{MutantClassName}} {{MutantClassNameLower}} = new {{MutantClassName}}();

    {{MethodReturnType}} resultO = {{OriginalClassNameLower}}.{{MethodName}}(AO);
    {{MethodReturnType}} resultM = {{MutantClassNameLower}}.{{MethodName}}(AM);

    assertEquals(resultO, resultM);     
  }
}

Then for example when a user submits a number 3 as input value, I manipulate the test template like this:

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertArrayEquals;
import static org.unitils.reflectionassert.ReflectionAssert.assertReflectionEquals;
import org.junit.Test;

public class CalculatorOCalculatorM0Test30099 {
  @Test
  public void isPrime() {
    int AO = 3;     
    int AM = 3;

    CalculatorO calculatorO = new CalculatorO();
    CalculatorM3 calculatorM3 = new CalculatorM3();

    boolean resultO = calculatorO.isPrime(AO);
    boolean resultM = calculatorM3.isPrime(AM);

    assertEquals(resultO, resultM);     
  }
}

Then I compile the test case and run it.

The main issue is that this cycle occurs often and because of the load forced to the server, because of files being created and compiled, the server faces low memory issue and crashes much.

I am looking for a way to create the test case one time and build it one time then run it for each input with arguments.

I mean something like this:

java -cp .;../../JUnitLibs/junit-4.12.jar;../../JUnitLibs/hamcrest-core-1.3.jar org.junit.runner.JUnitCore CalculatorOCalculatorM0Test30099 > CalculatorOCalculatorM0Test30099Result -input 3
6
  • 1
    Look into JUnit parameterized tests Commented May 3, 2017 at 5:43
  • I use Zohhak for parameterized tests: piotrturski.github.io/zohhak Commented May 3, 2017 at 6:24
  • @Dawood ibn Karim, This way the parameters should be present in the test class before file being built. But the argument (parameters) I mentioned come rapidly on run time. Commented May 3, 2017 at 6:25
  • 1
    Although a long time is from the answer posted but from that time I am using this solution and it is perfect. If any one needed the source code example I can share it too. Thanks @GhostCat. Commented Aug 24, 2017 at 19:31
  • @GhostCat, I think I didn't get your real meaning. If there is something that I can do just let me know. Thanks for your great answer. Commented Aug 24, 2017 at 20:44

1 Answer 1

1

One simple solution:

  • I would use properties to pass in those arguments on the command line
  • Add a @BeforeClass method to your testcase ... and there you turn to the properties, and read all required values from there.

In other words: you call your testcase with some -Darg1:value1 values; and your testcase does lookup "arg1"; and stores the provided value into some fields AO and AM for example.

Of course, you have to rework your code a bit; and the tricky part might be about variable types here (properties are all strings; but you probably want int, float, ... variables). Going on step further, you could simply create a helper class that provides methods like:

public static class PropertyWrapper {
  int getInt(String propertyName) { ...

and then you replace your pattern to something like

int AO = PropertyWrapper.getInt({{valueAPropertyName}});

Of course, this only works (easily) when you have different JVMs running the different user requests. Meaning: when you have two java runs, and give different args for each, then each unit test sees different values. When you have one JVM that is supposed to run this test multiple times with different arguments, then things become more complicated. You would then have that getInt() method have a list of values; and return one after the other; or something alike.

Sign up to request clarification or add additional context in comments.

3 Comments

are these system properties separate in each instance? I mean what if two test cases reach this phase same time?
And if I not being wrong, every process of java uses different JVM. Is this true?
I don't know how what your setup does. But when you are asking: "when calling java whatever" on the command line; will that result in independent JVM instances? The answer is simply: yes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.