Junit in Action - Note taking

Unit Test - A unit test examines the behavior of a distinct unit of work. Within a Java application, the "distinct unit of work" is often (but not always) a single method. By contract, integration tests and acceptance tests examine how various components interact. A unit work is a task that is not directly dependent on the completion of any other task.


All unit testing frameworks should follow:

1) Each unit test must run independently of all  other unit tests.

2) The framework must detect and report errors test by test.

3) It must be easy to define which unit tests will run.


The requirements to define a test class are that the class must be public and contain a zero-argument constructor.


The requirements to create a test method is that it must be annotated with @Test, be public, take no arguments, and return void.


difference between assertEquals and asertSame:

assertEquals("message", A, B) -- Assert equality of objects  A and B. This assert actually invokes the equals() method on the first object against the second.


assertSame("message", A, B) -- Asserts that A and B objects have the same value. While the previous assert method checks to see that both A and B are the same objects (using equals method), the assertSame method actually checks to see if the A and B objects have the same value ( using == operator)


The assertSame method confirms that both references are to the same object.

The assertEquals method utilizes the equals method, inherited from the base Object class. To see if two different objects have the same identity.


Running tests with the Parameterized test-runner:

@RunWith ( value=Parameterized.class)

public class ParameterizedTest {

private double expected;

private double valueOne;

private double valueTwo;


@Parameters

public static Collection dataParameters () {

return Arrays.asList ( new Object [][] {

{2, 1, 1},

{3, 2, 1},

{4, 3, 1},

} );

}


public ParameerizedTest (double expected, double valueOne, double valueTwo) {

this.expected = expcted;

this.valueOne = valueOne;

this.valueTwo = valueTwo;

}


@Test

public void sum () {

Calculator calc = new Calculator ();

assertEquals (expected, calc.add(valueOne, valueTwo), 0);

}

}


Compose test-methods from different test-classes:

@RunWith (value = org.junit.runners.Suite.class)

@SuiteClasses (value={TestFolderConfiguration.class,

TestFileConfiguration.class})

public class RunConfigurationTests {

...

}


Junit's details:

@Before/@After and @BeforeClass/@AfterClass annotated methods must bepublicby signature. The @BeforeClass/@AfterClass annotated methods must bepublicand also be static by signature.


The point of unit testing is to test one object at a time. In an object-oriented environment like Java, objects are designed to interact with other objects. To create a unit test, it follows that you need two flavors of objects: the domain object you are testing and test objects to interact with the object under test.


DEFINITION: domain object - In the context of unit testing, the term domain object is used to contract and compare the objects you use in you application with the objects that you use to test your application ( test objects). Any object under test is considered to be a domain object.


Junit best practices: unit-test one object at a time

A vital aspect of unit tests is that they are finely grained. A unit test independently examines each object you create, so that you can isolate problems as soon as they occur. If more than one object is put under test, you cannot predict how the objects will interact when changes occur to one or the other. When an object interacts with other complex objects, you can surround the object under test with predictable test objects. 


Junit best practices: choose meaningful test method names

You can see that a method is a test-method by the @Test annotation. But you also must be able to understand what a method is testing by reading the name. Although Junit does not imply any special rules for naming your test methods, a good rule is to start with the testXXX naming scheme, where XXX is the name of the method to test. As you add other tests against the same method, move to the testXXXYYY scheme, where YYY describes how the tests differ. Don't be afraid that the names of your tests are getting long. As you will see it is sometimes not so obvious what a method is testing simply by looking at the assert methods in it - so the only chance we have is - naming your test-methods in a descriptive fashion and putting comments where necessary.


Junit best practices: explain the failure reason in assert calls

Whenever you use any of the JUnit assert* methods, make sure you use the signature that takes a String as the first parameter. This parameter lets you provide a meaningful textual description that is displayed in the JUnit test runner if the assert fails. Not using this parameter makes it difficult to understand the reason for a failure when it happens.


Junit best practices: one unit test equals one @Test method

Do not try to cram several tests into one method. The result will be more complex test methods, which will become increasingly difficult to read and understand. Worse, the more logic you write in your test methods, the more risk there is that it will not work and will need debugging. This is a slippery slope that can end with writing tests to test your tests!


Unit tests  give you confidence in a program by alerting you when something that had worked now failed. If you put more than one unit test in a method, it makes it more difficult to zoom in on exactly what went wrong. When tests share the same method, a failing test may leave the fixture in an unpredictable state. Other tests embedded in the method may not run, or may not run properly. Your picture of the test results will often be incomplete or even misleading.


Because all the test methods in a TestClass share the same fixture, and JUnit can now generate an automatic test suite, it's really just as easy to place each unit test in its own method. If you need to use the same block of code in more than one test, extract it into a utility method that each test method can call. Better yet, if all methods can share the code, put it into the fixute.


Another common pitfall is to make test-methods that do not contain any assert statements. When you execute those tests yo use see JUnit flags them as successfully, but this is an illusion of successful tests. Don't do this!


For best results, your test methods should be as concise and focused as your domain methods.




Each test method must be as clear and focused as possible. This is why JUnit provides you with the @Before and @BeforeClass methods: so you can share fixtures between tests without combining test methods.



JUnit best practices: test anything that could possibly fail

Unit tests help ensure that your methods are keeping their API contracts with other methods. If the contract is based solely on other components's keeping their contracts, then there may not be any useful behavior for you to test. But if the method changes the parameter's or field's value in any way, then you are providing unique behavior that you should test. The method is no longer a simple go-between - it's a filtering or munging method with its own behavior that future changes could conceivably break. If a method is changed so it is not so simple anymore, then you should add a test when that change takes place. but not before. As the JUnit FAQ puts it, "The general philosophy is this: if it can't break on its own, it's too simple to break."


But what about things like JavaBean getters and setters? Well, that depends. If you are coding them by hand in a text editor, then yes, you might want to test them. It's surprisingly easy to miscode a setter in a way that the compiler won't catch. But if you are using an IDE that watches for such things, then your team might decide not to test simple JavaBean properties.


JUnit best practices: let the test improve the code

Writing unit tests often helps you write better code. The reason is simple: A test case is a user of your code. And, it is only when using code that you find its shortcomings. Thus, do not hesitate to listen to your tests and refactor your code so that it is easier to use. The practice of Test-Driven Development (TDD) relies on this principle. By writing the test first, you develop your classes from the point of view of a user of your code.

發佈了22 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章