Unit Testing Standards # Recommended Best PracticesDefinition of Unit TestingUnit testing is the execution and validation ...
•   All methods, regardless of visibility, should have appropriate unit tests. Public, private and protected methods that ...
Appendix 1. Summary Examples.Figure 1.                                                                         Figure 3.@T...
Appendix 2. Class Under Testpublic class StringNumber {    public String sum(final String arg1, final String arg2) {      ...
Appendix 4. FEST-Reflect in Reflection usage.One of the problems with Reflection is that its API is not very intuitive and...
Appendix 4. Mockito vs EasyMockEasyMock                                                            Differences            ...
Verification in order                         Stubbing void methodsEasyMock                                      EasyMock ...
Upcoming SlideShare
Loading in...5
×

Unit Testing Standards - Recommended Best Practices

1,227

Published on

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,227
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
25
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Unit Testing Standards - Recommended Best Practices

  1. 1. Unit Testing Standards # Recommended Best PracticesDefinition of Unit TestingUnit testing is the execution and validation of a block of code in isolation that a developer created. Because an object’s behavior is determined by itsmethod logic, we are going identifies a unit as a method within a class. Don’t write tests, write examples.Recommended Guideline • Write tests for methods that have the fewest dependencies first, and work your way up. If you start by testing a high-level method, your test may fail because a subordinate method may return an incorrect value to the method under test. This increases the time spent finding the source of the problem, and you will still have to test the subordinate method anyway to be sure it does not contain other bugs. • Tests should be logically simple as possible, preferably with no decisions at all. Every decision added to a test method increases the number of possible ways that a test method can be executed. Testing is meant to be a controlled environment, the only thing you want to change is the input to the method under test, not the test method itself. • Where possible, use constant expected values in your assertions instead of computed values. Consider these two assertions: returnVal = methodUnderTest(input); assertEquals(returnVal, computeExpectedReturnValue(input)); assertEquals(returnVal, 12); In order for computeExpectedReturnValue() to return the proper result it probably has to implement the same logic as the method under test, which is what you are trying to test for in the first place! Further, suppose you fixed a defect in the method under test. Now you have to change computeExpectedReturnValue() in the same manner. The second assertion is easier to understand and maintain. • Each unit test should be independent of all other tests. A unit test should execute one specific behavior for a single method. Validating behavior of multiple methods is problematic as such coupling can increase refactoring time and effort. Consider the following example: void shouldAdd(){ int return1 = myClass.add(1,2); int return2 = myclass.add(-1,-2); assertTrue (return1 - return2 == 0); } If the assertions fails in this case, it will be difficult to determine which invocation of add() caused the problem. • Each unit test should be clearly named and documented. The name of the test method should clearly indicate which method is being tested because improperly named tests increase maintenance and refactoring efforts. Comments should also be used to describe the test or any special conditions. 1 | Unit Testing Standards # Recommended Best Practices
  2. 2. • All methods, regardless of visibility, should have appropriate unit tests. Public, private and protected methods that contain data and decisions should be unit tested in isolation.• All unit tests should use appropriate coverage techniques to measure their effectiveness. Isolating coverage for each unit test independently of all other unit test is the only way to verify actual results. It is not appropriate to look at coverage numbers by themselves. Think of the situation where a unit test for Method A may increase the coverage for Method B as well. Even if Method B has coverage, unless the specific behavior was verified via an assertion, it should not be considered unit tested.• Strive for one assertion per test case. Multiple assertions in one test case can cause performance issues and bottlenecks. For example, if a test case with five assertions fails on the first assertion, then the remaining four are not executed. Only when the first assertion is corrected will the other assertions execute. If assertion two fails, then that also must be corrected before the remaining three assertions are verified. One major benefit of unit testing is to find the root cause of defects. Unit tests should be designed with this in mind, thus it is more economical to have one assertion per test case. Although the unit test file may be large, it will be easier to find and fix defects.• Create unit tests that target exceptions. Exceptions are thrown when a method finds itself in a state it cannot handle. These cases should be tested just like a method’s normal state of operations. If a method is declared to throw one or more exceptions, then unit tests must be create that simulate the circumstances under which those exceptions could be thrown. The unit tests should assert that the exceptions are thrown as expected.• Ultimate test template. The linguistic relativity principle (also known as the Sapir-Whorf Hypothesis) is the idea that the varying cultural concepts and categories inherent in different languages affect the cognitive classification of the experienced world in such a way that speakers of different languages think and behave differently because of it. @Test public void should...() throws Exception { // given ... // when ... // then … } If you have more then one statement in when, you may need a new example. If you have assertions outside then, you may need a new example too.• Stable test data as the Golden Rule. No matter how many times you run the test it should always give the same results. You must avoid using random test data and loops. Never use conditionals, you definitely need a new example or your example is broken. 2 | Unit Testing Standards # Recommended Best Practices
  3. 3. Appendix 1. Summary Examples.Figure 1. Figure 3.@Test @Testpublic void shouldSum() throws Exception { public void shouldPow() throws Exception { // given // given final String arg1 = "2"; final String arg1 = "2"; final String arg2 = "3"; final String arg2 = "3"; final String expectedResult = "5"; final String expectedResult = "8"; // when final StringNumber mockStringNumber = Mockito.mock(StringNumber.class); final String actualResult = new StringNumber().sum(arg1, arg2); Mockito.when(mockStringNumber.multiply("2", "2")).thenReturn("4"); Mockito.when(mockStringNumber.multiply("4", "2")).thenReturn("8"); // then Assertions.assertThat(actualResult).isNotEmpty().isEqualTo(expectedResult); // when} final String actualResult = new StringNumber().pow(arg1, arg2); // thenFigure 2. Assertions.assertThat(actualResult).isEqualTo(expectedResult);@Test }public void shouldThrowArithmeticException() throws Exception { // given final String arg1 = "2"; Figure 4. final String arg2 = "0"; @Test final String expectedMessage = "/ by zero"; public void shouldZero() throws Exception { // given // when final String arg1 = "-0"; ArithmeticException actualException = null; final String arg2 = "+0"; try { final String zeroNumber = "0"; new StringNumber().div(arg1, arg2); } catch (final ArithmeticException e) { // when actualException = e; final String actualResult = new StringNumber().sum(arg1, arg2); } // then // then Assertions.assertThat(actualResult).isNotEmpty().isNotSameAs(arg1) Assertions.assertThat(actualException).as("Should raise an .isNotSameAs(arg2).isEqualTo(zeroNumber);ArithmeticException:").hasMessage(expectedMessage); }} 3 | Unit Testing Standards # Recommended Best Practices
  4. 4. Appendix 2. Class Under Testpublic class StringNumber { public String sum(final String arg1, final String arg2) { return String.valueOf(Integer.valueOf(arg1).intValue() + Integer.valueOf(arg2).intValue()); } public String div(final String arg1, final String arg2) { return String.valueOf(Integer.valueOf(arg1).intValue() / Integer.valueOf(arg2).intValue()); } public String multiply(final String arg1, final String arg2) { return String.valueOf(Integer.valueOf(arg1).intValue() * Integer.valueOf(arg2).intValue()); } public String pow(final String arg1, final String arg2) { String result = arg1; for (int i = 1; i <= Integer.valueOf(arg2).intValue() - 1; i++) { result = this.multiply(result, arg1); } return String.valueOf(result); }}Appendix 3. FEST-Assert Usage Examples. • int removed = employees.removeFired(); • String[] newHires = employees.newHiresNames(); assertThat(removed).isZero(); assertThat(newHires).containsOnly("Gandalf", "Arwen", "Gimli"); • List<Employee> newEmployees = employees.hired(TODAY); • assertThat(yoda).isInstanceOf(Jedi.class) assertThat(newEmployees).hasSize(6).contains(frodo, sam); .isEqualTo(foundJedi) .isNotEqualTo(foundSith); 4 | Unit Testing Standards # Recommended Best Practices
  5. 5. Appendix 4. FEST-Reflect in Reflection usage.One of the problems with Reflection is that its API is not very intuitive and quite verbose. For example, to call the method: String name = names.get(8);using reflection, we need the following code: Method method = Names.class.getMethod("get", int.class); AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { method.setAccessible(true); return null; } }); String name = (String) method.invoke(names, 8);and with FEST-Reflect: String name = method("get").withReturnType(String.class) .withParameterTypes(int.class) .in(names) .invoke(8);which, in my opinion, is more compact, readable and type safe.The following examples demonstrate how easy is to access constructors, methods and fields using FEST-Reflect: • Person person = constructor().withParameterTypes(String.class) • field("name").ofType(String.class) .in(Person.class) .in(person) .newInstance("Yoda"); .set("Anakin"); • method("setName").withParameterTypes(String.class) • List<String> powers = field("powers").ofType(new TypeRef<List<String>>() {}) .in(person) .in(jedi) .invoke("Luke"); .get(); 5 | Unit Testing Standards # Recommended Best Practices
  6. 6. Appendix 4. Mockito vs EasyMockEasyMock Differences • only one kind of mock (no nice/default/strict mocks). Using EasyMock import static org.easymock.classextension.EasyMock.*; metaphor: Mockito mocks can be nice or strict - but it depends on List mock = createNiceMock(List.class); how you verify mocks, not how you create them. Because there is only one kind of mock - it is easier to share setup (situations where expect(mock.get(0)).andStubReturn("one"); mocks are fields in test class but different test methods require expect(mock.get(1)).andStubReturn("two"); different kinds of mocks). mock.clear(); • no record/replay modes - no need for them. There only 2 things you can do with Mockito mocks - verify or stub. Stubbing goes before replay(mock); execution and verification afterwards. • all mocks are nice (even nicer, because collection-returning methods someCodeThatInteractsWithMock(); return empty collections instead of nulls). Even though mocks are nice, you can verify them as strictly as you want and detect any verify(mock); unwanted interaction. • explicit language for better readability: verify() and stub() instead of mixture of expect() and ordinary method calls on mocks.Mockito • simplified stubbing model - stubbed methods replay all the time with import static org.mockito.Mockito.*; stubbed value no matter how many times they are called. Works exactly like EasyMocks andStubReturn(), andStubThrow(). Also, you List mock = mock(List.class); can stub with different return values for different arguments (like in EasyMock). when(mock.get(0)).thenReturn("one"); • Verification of stubbed methods is optional because usually its more when(mock.get(1)).thenReturn("two"); important to test if the stubbed value is used correctly rather than wheres it come from. someCodeThatInteractsWithMock(); • verification is explicit - verification errors point at line of code showing what interaction failed. verify(mock).clear(); • only one way of creating mocks (no MockControl object). • verification in order is flexible and doesnt require to verify every single interaction.Similarities • custom argument matchers use hamcrest matchers, so you can use • allow the same level verification as EasyMock (unexpected your existing hamcrest matchers. (EasyMock also integrates with invocations, redundant invocations, verification in order) hamcrest, see the documentation of hamcrest). • argument matchers (anyInt(), anyObject(), etc.) 6 | Unit Testing Standards # Recommended Best Practices
  7. 7. Verification in order Stubbing void methodsEasyMock EasyMock Control control = createStrictControl(); List mock = createNiceMock(List.class); List one = control.createMock(List.class); mock.clear(); List two = control.createMock(List.class); expectLastCall().andThrow(new RuntimeException()); expect(one.add("one")).andReturn(true); replay(mock); expect(two.add("two")).andReturn(true); control.replay(); Mockito someCodeThatInteractsWithMocks(); List mock = mock(List.class); control.verify(); doThrow(new RuntimeException()).when(mock).clear(); Exact number of times verification and argument matchersMockito EasyMock List one = mock(List.class); List two = mock(List.class); List mock = createNiceMock(List.class); someCodeThatInteractsWithMocks(); mock.clear(); expectLastCall().times(3); InOrder inOrder = inOrder(one, two); expect(mock.add(anyObject())).andReturn(true).atLeastOnce(); inOrder.verify(one).add("one"); someCodeThatInteractsWithMock(); inOrder.verify(two).add("two"); replay(mock); Mockito List mock = mock(List.class); someCodeThatInteractsWithMock(); verify(mock, times(3)).clear(); verify(mock, atLeastOnce()).add(anyObject()); 7 | Unit Testing Standards # Recommended Best Practices
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×