Top Banner
Unit Testing Unit Testing Bartosz Walter <[email protected]> Software Engineering Lecture XXX
41

Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Dec 29, 2015

Download

Documents

Jane Briggs
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Unit TestingUnit Testing

Bartosz Walter<[email protected]>

Software Engineering Lecture XXX

Page 2: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

AgendaAgenda

1. JUnit – a unit testing library for Java2. Guidelines for creating test cases3. Smells in tests4. Implementation tasks

Page 3: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Schemat klas jUnitSchemat klas jUnit

TestCase

Test

TestSuiteTestResult

RomanNumberTest

Page 4: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

TestCaseTestCase

MyTestvoid testXXXX()

void tearDown()

void setUp()

junit.framework.TestCase

void testYYYY()

void testZZZZ()

void testWWWW()

void testXXXX()

void testYYYY()

void testZZZZ()

MyTest(name)

Page 5: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

StudentTest.java

Klasa i jej klasa testowaKlasa i jej klasa testowa

+ testComputeLevel()

+ testGetAge()

+ testGetName()

+ tearDown()

+ setUp()

+ computeLevel()

+ getAge()

+ getName()

Student.java

Utworzenie instancji klasy Student

Usunięcie instancji klasy Student

– Student student

Page 6: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

TestCaseTestCase

MyTestvoid testXXXX()

void tearDown()

void setUp()

junit.framework.TestCase

void testYYYY()

void testZZZZ()

void testWWWW()

void testXXXX()

void testYYYY()

void testZZZZ()

MyTest(name)

Page 7: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Simplest test possible...Simplest test possible...

void tearDown()

void setUp()

void testSimple()

public void setUp() { rn1 = new RomanNumber(5); rn2 = new RomanNumber(20);}

public void testSimple()throws Exception {

String str = rn1.toString(); assertEquals(str, "V");

}

public void tearDown() { rn1 = null; rn2 = null;}

RomanNumberTest(name)public RomanNumberTest(name){ super(name);}

Page 8: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Failure vs. errorFailure vs. error

Failure: anticipated violation of the test assertion signals that the test actually fails

Error: unanticipated exception caught by the test runner the test could not be run properly

Page 9: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Failure vs. errorFailure vs. error

public void testNonexistentFileRead() throws IOException { try { File file = new File("doesNotExist.txt"); FileReader reader = new FileReader(file); assertEquals('a', (char) reader.read()); fail("Read from a nonexistent file?!"); } catch (FileNotFoundException success) {} }

public void testExistingFileRead() throws IOException { // exists.txt created in setup(), perhaps File file = new File("exists.txt"); FileReader reader = new FileReader(file);

assertEquals('a', (char) reader.read()); }

Page 10: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Basic functionality of a Basic functionality of a TestCaseTestCase

Groups of methods: equality tests

void assertEquals([msg], expected, actual) identity tests

void assertSame([msg], expected, actual) void assertNotSame ([msg], expected, actual)

boolean tests void assertTrue([msg], condition) void assertFalse([msg], condition)

null tests void assertNull([msg], object) void assertNotNull([msg], object)

unconditional failure void fail([msg])

Page 11: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Creating Creating TestSuiteTestSuites staticallys statically

public class RomanNumberTest extends TestCase {

public RomanNumberTest(String name) { super(name); }

// testing methods public void testSimpleConv() {} public void testAddition() {}

public static Test suite() { TestSuite suite = new TestSuite(); suite.addTest(new MyTest("testSimpleConv")); suite.addTest(new MyTest("testAddition")); return suite; } }

Page 12: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Creating Creating TestSuiteTestSuites dynamicallys dynamically

public class RomanNumberTest extends TestCase {

public RomanNumberTest(String name) { super(name); }

// testing methods public void testSimpleConv() {} public void testAddition() {}

public static Test suite() { TestSuite suite = new TestSuite(); suite.addTestSuite(MyTest.class) return suite; } }

Page 13: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Guidelines for creating Guidelines for creating TestCaseTestCasess

Don't use constructor for initializing the TestCase

junit.framework.AssertionFailedError: Cannot instantiate test case: test1

at junit.framework.Assert.fail(Assert.java:143)     at junit.framework.TestSuite$1.runTest(TestSuite.java:178)at junit.framework.TestCase.runBare(TestCase.java:129)  at junit.framework.TestResult$1.protect

(TestResult.java:100)  ...

public class SomeTest extends TestCase { public SomeTest (String testName) { super (testName); // Perform test set-up }}

Page 14: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Guidelines for creating Guidelines for creating TestCaseTestCasess

Don't use constructor for initializing the TestCase

public class SomeTest extends TestCase { public SomeTest (String testName) { super (testName); } public void setUp() { // Perform test set-up }}

java.lang.IllegalStateException: Oopsat bp.DTC.setUp(DTC.java:34)   at junit.framework.TestCase.runBare(TestCase.java:127)at junit.framework.TestResult$1.protect(

TestResult.java:100) ...

Page 15: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Guidelines for creating TestCasesGuidelines for creating TestCases

Don't assume the order in which tests within a TestCase are executedAvoid writing TestCases with side effects

public class SomeTestCase extends TestCase {

public SomeTestCase (String testName) { super (testName); }

public void testDoThisFirst () { }

public void testDoThisSecond () { } }

Page 16: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Guidelines for creating TestCasesGuidelines for creating TestCases

Don't assume the order in which tests within a TestCase are executedAvoid writing TestCases with side effects

public class SomeTestCase extends TestCase { public void testDoThisFirst () { }

public void testDoThisSecond () { }

public static Test suite() { suite.addTest(new SomeTestCase("testDoThisFirst";)); suite.addTest(new SomeTestCase("testDoThisSecond";)); return suite; } }

Page 17: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Guidelines for creating TestCasesGuidelines for creating TestCases

Avoid using hardcoded resourcesWrite self-contained testsPlace tests in the same packages as source code

public class SomeTestCase extends TestCase { public void setUp () {   FileInputStream inp ("C:\\TestData\\dataSet1.dat"); // .. }}

Page 18: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Guidelines for creating TestCasesGuidelines for creating TestCases

Avoid using hardcoded resourcesWrite self-contained testsPlace tests in the same packages as source code

public class SomeTestCase extends TestCase { public void setUp () { InputStream inp = class.getResourceAsStream (this.getClass (), "dataSet1.dat"); }}

Page 19: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Guidelines for creating TestCasesGuidelines for creating TestCases

Avoid time/locale-sensitive tests

Date date = DateFormat.getInstance().parse("dd/mm/yyyy");

Calendar cal = Calendar.getInstance();Cal.set(yyyy, mm-1, dd);Date date = Calendar.getTime();

Locale locale = Locale.getDefault();

Page 20: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Guidelines for creating TestCasesGuidelines for creating TestCases

Use JUnit assert/fail methods for throwing ExceptionsDon't catch exceptions unless they are expected to be thrown

public void exampleTest() { try { // do some testing } catch (SomeApplicationException ex) { fail ("Caught SomeApplicationException exception"); }}

Page 21: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Guidelines for creating TestCasesGuidelines for creating TestCases

public void testIndexOutOfBoundsException() {

ArrayList emptyList = new ArrayList();

try { Object o = emptyList.get(0); fail("IndexOutOfBoundsException expected"); } catch (IndexOutOfBoundsException success) { } }

If the test should pass on exception thrown, catch the exception within the test and place fail() if it is not thrown

Page 22: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Guidelines for creating TestCasesGuidelines for creating TestCases

public void exampleTest () throws SomeApplicationException { // do some test}

Use JUnit assert/fail methods for throwing ExceptionsDon't catch exceptions unless they are expected to be thrown

Page 23: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Guidelines for creating TestCasesGuidelines for creating TestCases

Beware of floating-point comparison errors

assertEquals ("The result is different from what is expected", result, expected);

assertEquals ("The result is different from what is expected", 0.05 + 0.05, 1/10.0);

assertEquals ("The result is definitely different from what is expected ", result, expected, delta);

assertEquals ("The result is definitely different from what is expected", 0.05 + 0.05, 1/10.0, 0.01);

Page 24: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Guidelines for creating TestCasesGuidelines for creating TestCases

Testing protected and private methods

Protected: Place the tests in the same package as the classes

under test.

Private: avoid use Java Reflection to call a private method

Page 25: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Guidelines for creating TestCasesGuidelines for creating TestCases

Organizing files in catalog

| +--src | | | +--com | | | +--xyz | | | +--SomeClass.java +--test | +--com | +--xyz | +--SomeClassTest.java

com.xyz.SomeClass

com.xyz.SomeClassTest

Page 26: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Task 1Task 1

Write tests for existing code of RomanNumber class

Page 27: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

RomanNumberRomanNumber

class RomanNumber { // initialize with an Arabic year public RomanNumber(int number); // initialize with a Roman year public RomanNumber(String number); // return the Roman value public String toRoman(); // return the Arabic value public int toArabic(); // return a Collection of legal Roman symbols public static Collection getRomanSymbols();}

Page 28: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Task 2Task 2

Implement RomanNumber class using test-first approach.

Page 29: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Testing firstTesting first

TestCase: INPUT: 1, EXPECTED: "I"

Implementation:String toArabic(int num) { return "I";}

Page 30: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Testing firstTesting first

TestCase: INPUT: 2, EXPECTED: "II"

Implementation:String toArabic(int num) { if (num == 1) return "I"; else return "II";}

Page 31: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Testing firstTesting first

TestCase: INPUT: 3, EXPECTED: "III"

Implementation:String toArabic(int num) { if (num == 1) return "I"; else if (num == 2) return "II"; else return "III";}

Page 32: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Testing firstTesting first

TestCase: INPUT: 3, EXPECTED: "III"

Implementation:String toArabic(int num) { while (num-- > 0) result += "I"; return result;}

Refactoring

Page 33: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Testing firstTesting first

TestCase: INPUT: 4, EXPECTED: "IV"

Implementation:String toArabic(int num) { if (num < 4) while (num-- > 0) result += "I"; return result; } return "IV";}

Page 34: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Testing firstTesting first

TestCase: INPUT: 5, EXPECTED: "V"

Implementation:String toArabic(int num) { if (num < 4) while (num-- > 0) result += "I"; return result; } else if (num == 4) { return "IV"; } else { return "V"; }}

Page 35: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Testing firstTesting first

TestCase: INPUT: 6, EXPECTED: "VI"

Implementation:String toArabic(int num) { if (num < 4) while (num-- > 0) result += "I"; return result; } else if (num == 4) { return "IV"; } else if (num == 5) { return "V"; } else return "VI";}

Page 36: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Testing firstTesting first

TestCase: INPUT: 8, EXPECTED: "VIII"

Implementation:String toArabic(int num) { if (num < 4) while (num-- > 0) result += "I"; return result; } else if (num == 4) { return "IV"; } else { result = "V"; while (num-- > 5) result += "I"; return result; }}

Refactoring

Page 37: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Testing firstTesting first

TestCase: INPUT: 9, EXPECTED: "IX"

Implementation:String toArabic(int num) { // 1..4.. else if (num < 9) { result = "V"; while (num-- > 5) result += "I"; return result; } else { return "IX"; }}

Page 38: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Testing firstTesting first

TestCase: INPUT: 10, EXPECTED: "X"

Implementation:String toArabic(int num) { // 1..4.. else if (num < 9) { result = "V"; while (num-- > 5) result += "I"; return result; } else (num == 9) { return "X"; } else { return "IX";}

Page 39: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Testing firstTesting first

TestCase: INPUT: 1976, EXPECTED: "MCMLXXVI"

Implementation:private class ConvSymbols {int arabic, String roman}{{1,I}, {4,IV}, {5,V}, {9,IX}, {10,X}, {40,XL}, ...}

String toArabic(int num) { for (int i = 0; i < sizeof(symbols); i++) { Symbol sym = symbols[i]; while (num >= symbol.arabic) { num -= symbol.arabic; result += symbol.roman; } }}

Refactoring

Page 40: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

BibliographyBibliography

1. JUnit, http://www.junit.org/

2. Test Infected – Programmers love writing tests, http://junit.sourceforge.net/doc/testinfected/testing.htm

3. JUnit Cook's Tour, http://junit.sourceforge.net/doc/cookstour/cookstour.htm

4. Unit-testing Tools, http://www.xprogramming.com/software.htm

Page 41: Unit Testing Bartosz Walter Software Engineering Lecture XXX.

Q&AQ&A