270 likes | 595 Views
Greg Barnes University of Washington gsbarnes@washington.edu. Unit and Functional Testing with JUnit and Related Tools. Introduction. Testing JUnit, etc. Best practices from the testing community My best practices. Types of Testing. Unit testing: Does a single object work?
E N D
Greg Barnes University of Washington gsbarnes@washington.edu Unit and Functional Testing with JUnit and Related Tools
Introduction • Testing • JUnit, etc. • Best practices from the testing community • My best practices
Types of Testing • Unit testing: Does a single object work? • Integration testing: Do multiple objects work together? • Functional testing: Does my application work? • Performance testing: Does my application work well? • Acceptance testing: Does the customer like my application?
Why Test? • No-brainers: Functional, Acceptance, Performance testing • Why Unit Test? • Coverage, especially of strange conditions • Facilitates teamwork, lessens 'ownership' • Confidence in your own work • Enable refactoring • Self-documentation of API • Improve design
How to use tests • A common testing cycle: • Write some new code OR Fix a bug OR Refactor some code • Run tests to ensure the now-changed code works • Check the new code in
Basic testing principles • For things that can be tested automatically, tests should be: • easy to write • easy to run • objective (easy to see if they pass or fail) • repeatable (deterministic)
JUnit • Open source framework for testing Java code • Attempts to make writing unit tests easy • Structure: • TestSuites • TestCase [Java class] • Test [Java method] • Fixtures: common setup/teardown code • Most often you write TestCases, Tests, and Fixtures
Example import junit.framework.TestCase; public class TestString extends TestCase { public void testEndsWith() { assertTrue(“abcabc”.endsWith(“abc”)); } public void testEndsWithEmptyString() { assertTrue(“Doesn't end with empty string!”, “abcabc”.endsWith(“”)); } }
Some best practices • TestCases (Java classes) • Usually test a single Java class • Name starts or ends with Test • Tests (Java methods) • test a single method • testXxx tests method xxx • multiple tests of method xxx are named testXxxYyy, where Yyy describes a particular condition, e.g., testEndsWithEmpty • Label your assertions • One test per test method
More details • fixtures: setUp, tearDown • assertFalse, assertEquals, assertNotEquals, assertNull, etc., etc. • JUnit 4/Java 5 – some incremental improvements
Running JUnit tests • Many ways: • Command line • IDE (Eclipse plug-in, etc.) • Ant • Maven • Various ways of viewing output (text, XML -> Web page, ...)
More best practices • Run your tests using a tool: IDE, Ant, Maven… • Tests should be independent • Same package, different directory src test org org jasig jasig SomeClass.java TestSomeClass.java OtherClass.java TestOtherClass.java
Related tools • “xUnit” - e.g., CUnit for C • WebTest, HttpUnit – web applications • DBUnit – database-driven code • Cactus – J2EE components • Code coverage tools – Do my tests cover all possible lines of code? • Continuous testing tools – Run tests on a schedule, or whenever code is checked in
Functional testing • For web applications: WebTest, HttpUnit, Cactus, JMeter... • HttpUnit and Cactus tests are like JUnit • WebTest uses XML to specify tests • JMeter has a GUI (and writes XML) • All require a special environment to run tests • Functional tests usually are slower than unit tests • Functional tests usually are run separately from unit tests
Best practices from the testing community • If it’s hard to write a test, the code your testing should probably be changed. • To test a private method, make it protected (or package-protected)
Best Practices from the testing communityII • Test anything that can reasonably break
Best practices from the testing community III • Always verify that tests fail when they should • Particularly important if you’re fixing a bug • Test-Driven Development • Always write a failing test before writing any new code • Refactor
Best Practices from the testing communityIV • Test one object at a time • Stubs, mock objects
Mock Objects • Allow you to test a class that relies on other, non-trivial objects, particularly objects that are difficult to instantiate or slow • Mock versions of many popular classes (e.g., HttpRequest)available, as well as packages that create Mocks automatically
Example Want to test DB.getUser(User, Callback), but it's hard to create a Callback object. public void testGetUser() { Callback mc = new MockCallback(); assertNotNull(DB.getUser(new User(), mc) }
More on Mocks • Mocks can keep track of how they were used, so you can check in with them afterwards to make sure the class you're testing performed the operations you expected
Example Check that DB.getUser(User, Callback) actually does what it's supposed to do with the Callback object MockCallback mc = new MockCallback(); mc.expects([something]); mc.expects([something else]); assertNotNull(DB.getUser(new User(), mc); mc.verify();
My best practices • Write tests that work and are easy to use. • Don’t reject tests if they work and are easy to use. • Create a test whenever fixing a bug. Make sure it fails before fixing the code. • Create a test when adding a new feature, or ‘tricky’ code. • Write clean test code.
Best practices you can break • If it helps you write and run tests more often: • Ignore test-driven design • Don’t obsess about testing `anything that could possibly fail’ • Test more than one object at once • But… • Learn about mock objects • Learn about other tools
Conclusions • Testing is good • Don't put barriers in the way of writing and running tests • Learn about the testing toolbox, and be prepared to use the tools as appropriate
References • http://www.junit.org • http://httpunit.sourceforge.net • JUnit in Action – Vincent Massol • Java Development with Ant – Erik Hatcher, Steve Loughran
Sample project rules relating to tests • If a change you make creates a bug, and the tests don’t pass, it’s your fault. • Don’t check in code unless the tests pass. • If a change you make creates a bug (in other code), and the tests pass, it’s the fault of whoever wrote the other code. • Write more tests.