[Go] using JUNIT4 for unit testing in Eclipse (Advanced article)

Source: Internet
Author: User

With the first 2 articles, you must have a basic understanding of junit, let's look at some of the advanced features in JUNIT4.

First, advanced fixture

In the previous article we introduced two fixture annotations, namely @before and @after, to see if they are suitable for the following functions: one class is responsible for reading and writing large files (more than 500 megabytes), and each of his methods is manipulating the files. In other words, before invoking each method, we have to open a large file and read the contents of the file, which is definitely a time-consuming operation. If we use @before and @after, then each test will have to read the file once, efficiency and low. What we want here is to read the file at the start of all tests, release the file after all the tests are finished, and not read the file every time. The JUnit authors clearly consider this issue, which gives @BeforeClass and @AfterClass two fixture to help us achieve this function. As can be seen from the name, using the functions labeled in these two fixture, only the @BeforeClass method is executed when the test case is initialized, and after all the tests have been executed, the @afterclass is performed to finish the work. Note here that only one method per test class can be labeled as @BeforeClass or @AfterClass, and that the method must be public and static.

Second, time-limited testing

Remember the example I gave in my introductory article, the function that squared root has a bug, is a dead loop:

public void SquareRoot (int n)    {for        (;;);    Bug: Dead Loop    }

If you encounter a dead loop during testing, you will never smile on your face. Therefore, for those whose logic is very complex, the loop nesting is relatively deep, there is a possibility of a dead loop, so it is necessary to take some precautions. Time-limited testing is a good solution. We set an execution time for these test functions, more than that, they will be forcibly terminated by the system, and the system will report to you the reason for the end of the function is because of the timeout, so you can find these bugs. To do this, you only need to add a parameter to the @test callout, and the code is as follows:

    @Test (timeout=1000) public    void Testadd () {        calculator.squareroot (4);        Assertequals (2, Calculator.getresult ());    }
Operation Result:

The timeout parameter indicates the time you want to set, in milliseconds, so 1000 represents 1 seconds.

Third, test the exception

Exception handling in Java is also a priority, so you will often write some functions that need to throw exceptions. So, if you think a function should throw an exception, but it's not thrown, does that count as a bug? This is certainly a bug, and JUnit has taken this into account to help us find this bug. For example, we write the Calculator class has the division function, if the divisor is a 0, then must throw "except 0 exception". Therefore, it is necessary for us to test these. The code is as follows:

   @Test (expected =arithmeticexception.class) public    void Testdivide () {        calculator.add (8);        Calculator.divide (0);        Assertequals (4,calculator.getresult ());    }

如上述代码所示,我们需要使用@Test the expected attribute of the callout, pass the exception that we want to test to him, so that the JUnit framework can automatically help us detect if the exception we specified is thrown.

Four, Runner (running device)

Have you ever thought about this question, how does the framework run your code when you submit the test code to the JUnit framework? The answer is--runner. There are many runner in JUnit, they are responsible for invoking your test code, each runner has its own special features, and you need to choose different runner to run your test code as needed. Perhaps you will find it strange that we have written so many tests before, and have not explicitly specified a runner ah? This is because there is a default runner in JUnit, and if you do not specify it, the system automatically uses the default runner to run your code. In other words, the following two paragraphs of code mean exactly the same:

Import Org.junit.internal.runners.testclassrunner;import org.junit.runner.RunWith; @RunWith (testclassrunner.class public class Calculatortest {...} The system default Testclassrunner is used, exactly as in the following code, public class Calculatortest {...}

As you can see from the above example, to specify a runner, you need to use the @runwith callout and pass the runner you specify as a parameter to it. Another thing to note is that the @RunWith is used to modify the class, not to modify the function. All functions in this class are called by this runner whenever a runner is specified for a class. Finally, do not forget to include the appropriate package, the above example is very clear. Next, I'll show you the unique features of other runner.

Five, parametric test

You may have encountered such a function, its parameters have many special values, or his parameters are divided into a number of areas. For example, a function to evaluate test scores, the return value is "good, good, general, pass, fail", so you write the test, at least to write 5 tests, the 5 is included in the situation, this is really a very troublesome thing. We also use our previous example to test the "calculate the square of a number" this function, for the moment divided into three categories: positive, 0, negative. The test code is as follows:

Import Org.junit.afterclass;import org.junit.before;import Org.junit.beforeclass;import Org.junit.Test;import Static org.junit.assert.*; public class Advancedtest {private static Calculator Calculator = new Calculator ();     @Before public    void Clearcalculator () {        calculator.clear ();    }     @Test public    void Square1 () {        calculator.square (2);        Assertequals (4, Calculator.getresult ());    }    @Test public    void Square2 () {        calculator.square (0);        Assertequals (0, Calculator.getresult ());    }    @Test public    void Square3 () {        calculator.square ( -3);        Assertequals (9, Calculator.getresult ());}    }

To simplify a similar test, JUNIT4 puts forward the concept of "parametric testing", writing only one test function, passing in several cases as parameters, and testing them once. The code is as follows:

Import static Org.junit.assert.*;import Java.util.collection;import Java.util.arrays;import Org.junit.Test;import Org.junit.runner.runwith;import Org.junit.runners.parameterized;import org.junit.runners.Parameterized.Parameters; @RunWith (parameterized.class) public class Squaretest {    private static Calculator Calculator = new Calculator ();    private int param;    private int result;        @Parameters public    static Collection data () {        return arrays.aslist (new object[][]{                {2, 4},                {0, 0},                { -3, 9}        });    }        constructor, initializes the variable to public    squaretest (int param,int result)    {        this.param=param;        This.result=result;    }        @Test public    void Square ()    {        calculator.square (param);        Assertequals (Result,calculator.getresult ());        System.out.println ("result=" +result);}    

Below we analyze the above code. First, you want to create a new class for this kind of test instead of sharing the same class with other tests, in which case we define a squaretest class. Then, you want to specify a runner for this class, but not the default runner, because special functions need to use special runner.

@RunWith (Parameterized.class) This statement specifies a parameterizedrunner for this class.

The second step is to define a class to be tested and define two variables, one for storing parameters and one for storing the expected results.

Next, define a collection of test data, the data () method described above, which can be arbitrarily named, but must be decorated with @parameters annotations. The framework of this method will not explain, you just need to pay attention to the data, is a two-dimensional array, data 221 groups, each group of the two data, one is the parameter, one is the result you expect. For example, our first set of {2, 4},2 is the parameter, and 4 is the expected result. The order of the two data does not matter, who before who can.

The constructor is followed by the function of initializing the two parameters previously defined. Here you have to pay attention to the order of the parameters, consistent with the order of the data set above. If the previous order is {parameter, expected result}, then the order of your constructor is also "constructor (parameter, expected result)" and vice versa. The last is to write a simple test example, and the previous introduction of the same wording, not much to say here.

Six, packaging testing

From the previous introduction we can feel that in a project, it is impossible to write only one Test class, we will write many many test classes. But these test classes have to be executed one by one, and it's a bit of a hassle. With this in mind, JUnit provides us with the ability to package tests, centralize all the test classes that need to be run, and run them all at once, greatly facilitating our testing efforts. The specific code is as follows:

Import Org.junit.assert.*;import org.junit.runner.runwith;import org.junit.runners.Suite; @RunWith (Suite.class) @ Suite.suiteclasses ({        calculatortest.class,        squaretest.class        }) public class Allcalculatortests {}

Operation Result:

As you can see, this feature also needs to use a special runner, so we need to pass a parameter suite.class to the @runwith callout. At the same time, we need another callout @suite.suiteclasses to show that this class is a packaged test class. We pass the class that needs to be packaged as a parameter to the callout. With these two annotations, all of the meanings have been fully expressed, so the following classes are irrelevant, with a class name, and the contents are all empty.

JUnit provides a way to run a test class in batches, called a test suite.

The test suite should be written in the following guidelines:

1. Create an empty class as the entrance to the test suite;

2. Use annotations Org.junit.runner.RunWith and org.junit.runners.Suite.SuitClasses to decorate this empty class

3. Pass the Org.junit.runners.Suite as a parameter to the annotation runwith to prompt JUnit to use the Suite runner for this type of test execution.

4. Make an array of the test classes that need to be put into this test suite as parameters for the annotation suiteclasses

5. Ensure that the empty class is decorated with public and that there are exposed constructors with no arguments.

At this point, this series of articles are all finished, hoping to be able to use JUNIT4 to help you.

[Go] using JUNIT4 for unit testing in Eclipse (Advanced article)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.