Why are software tests helpful?
Software unit tests help the developer to verify
that the logic of a piece of the program is correct.
Running tests automatically helps to identify
software regressions(less developed state) introduced by changes in the source
code. Having a high test coverage of your code allows you to continue
developing features without having to perform lots of manual tests.
Unit tests and unit testing
A unit
test is a piece of
code written by a developer that executes a specific functionality in the code
to be tested and asserts a certain behaviour or state.
The percentage of code which is
tested by unit tests is typically called test coverage.
A unit test targets a small
unit of code, e.g., a method or a class, (local tests). External dependencies
should be removed from unit tests, e.g., by replacing the dependency with a
test implementation or a (mock) object created by a test framework.
Integration tests
An integration test has the target to test the behaviour of
a component or the integration between a set of components.
Integration tests check that
the whole system works as intended, therefore they are reducing the need for
intensive manual tests.
This kind of tests allow you to
translate your user stories into a test suite, i.e., the test would resemble an
expected user interaction with the application.
Performance tests
Performance
tests are used to benchmark software components repeatedly. Their purpose is to
ensure that the code under test runs fast enough even if it's under high load.
Where should the test be located?
Typical unit tests are created
in a separate project or separate source folder to keep the test code separate
from the real code.
Which part of the software should be tested?
In any case you should write
software tests for the critical and complex parts of your application. If you
introduce new features a solid test suite also protects you against regression
in existing code.
Which part of the software should not be tested?
In general it is safe to ignore
trivial code as, for example, getter and setter methods which simply assign
values to fields. Writing tests for these statements is time consuming and
pointless, as you would be testing the Java virtual machine. The JVM itself
already has test cases for this and if you are developing end user applications
you are safe to assume that a field assignment works in Java.
How to define a test in JUnit?
A JUnit test is a method contained in a class which
is only used for testing. This is called a Test class.
To write a test with the JUnit
4.x framework you annotate a method with the
@org.junit.Test annotation.
In this method you use an assert method, typically provided by the
JUnit or another assert framework, to check the expected result of the code
execution versus the actual result. These method calls are typically called asserts or assert statements.
You should provide meaningful
messages in assert statements so that it is easier for the developer to
identify the problem. This helps in fixing the issue, especially if someone
looks at the problem, who did not write the code under test or the test code.
JUnit test suites
If you
have several test classes, you can combine them into a test
suite. Running a test suite will execute all test classes in that
suite in the specified order.
@RunWith(Suite.class)
@Suite.SuiteClasses({
JunitTest1.class,
JunitTest2.class
})
JUnit annotations
Annotation
|
Description
|
@Test
public void method() |
The @Test annotation
identifies a method as a test method.
|
@Test (expected = Exception.class)
|
Fails if the method does not throw
the named exception.
|
@Test(timeout=100)
|
Fails if the method takes longer
than 100 milliseconds.
|
@Before
public void method() |
This method is executed before
each test. It is used to prepare the test environment (e.g., read input data,
initialize the class).
|
@After
public void method() |
This method is executed after each
test. It is used to cleanup the test environment (e.g., delete temporary
data, restore defaults). It can also save memory by cleaning up expensive
memory structures.
|
@BeforeClass
public static void method() |
This method is executed once,
before the start of all tests. It is used to perform time intensive
activities, for example, to connect to a database. Methods marked with this
annotation need to be defined as static to
work with JUnit.
|
@AfterClass
public static void method() |
This method is executed once,
after all tests have been finished. It is used to perform clean-up
activities, for example, to disconnect from a database. Methods annotated
with this annotation need to be defined as static to
work with JUnit.
|
@Ignore or @Ignore("Why
disabled")
|
Ignores the test method. This is
useful when the underlying code has been changed and the test case has not
yet been adapted. Or if the execution time of this test is too long to be
included. It is best practice to provide the optional description, why the
test is disabled.
|
Assert statements
JUnit provides static
methods in the Assert class to test for certain conditions.
These assert statements typically start withassert and allow you to specify the error message, the expected and
the actual result. An assertion method compares the actual
value returned by a test to the expected value, and throws an AssertionException if the comparison test fails.
Description
|
|
fail(message)
|
Let the
method fail. Might be used to check that a certain part of the code is not
reached or to have a failing test before the test code is implemented. The
message parameter is optional.
|
assertTrue([message,]
boolean condition)
|
Checks
that the boolean condition is true.
|
assertFalse([message,]
boolean condition)
|
Checks
that the boolean condition is false.
|
assertEquals([message,]
expected, actual)
|
Tests that
two values are the same. Note: for arrays the reference is checked not the
content of the arrays.
|
assertEquals([message,]
expected, actual, tolerance)
|
Test that
float or double values match. The tolerance is the number of decimals which
must be the same.
|
assertNull([message,]
object)
|
Checks
that the object is null.
|
assertNotNull([message,]
object)
|
Checks
that the object is not null.
|
assertSame([message,]
expected, actual)
|
Checks
that both variables refer to the same object.
|
assertNotSame([message,]
expected, actual)
|
Checks
that both variables refer to different objects.
|
.
Test execution order
JUnit assumes that all test
methods can be executed in an arbitrary order. Well-written test code should
not assume any order, i.e., tests should not depend on other tests.
You can use an annotation to define that the test methods are
sorted by method name, in lexicographic order. To activate this feature,
annotate your test class with the
@FixMethodOrder(MethodSorters.NAME_ASCENDING) annotation.
JUnit
Simple Example
Calculate.java
public class Calculate {
|
public int sum(int var1, int var2) {
|
System.out.println("Adding values:
" + var1 + " + " + var2);
|
return var1 + var2;
} } |
CalculateTest.java
import static org.junit.Assert.*;
|
import org.junit.Test;
|
public class CalculateTest {
|
Calculate calculation = new Calculate();
|
int sum = calculation.sum(2, 5);
|
int testSum = 7;
|
@Test |
public void testSum() {
|
System.out.println("@Test sum(): " + sum + " = " + testSum);
|
assertEquals(sum, testSum);
|
}
|
}
|
Run As ->
Junit Test
Adding values: 2 + 5
|
@Test sum(): 7 = 7
|
if we change this line of code:
int testSum = 10; |
so that
the integers to be tested are not equal, the output will be:
Adding values: 2 + 5 |
@Test sum(): 7 = 10 |
And in
the JUnit window, an error will appear and this message will be displayed:
java.lang.AssertionError |
0 comments :
Post a Comment