Lectures‎ > ‎Week 5:June 27-July 3‎ > ‎

04-Testing, Junit, TDD

Homework required in preparation for this lecture

  1. Read Junit Tutorial and do the indicated steps.
    1. In addition add a method to MyClass and a test to MyClassTest. The method should throw an exception in some case, and the test should ensure that the exception was thrown, as expected.
    2. Deliverable: Upload your code to Github and do a Screencast. Include links in your homework log.
  2. Apply this to your product
    1. Isolate at least one class from your product. What I mean is to locate a class that does not depend on any other classes, or if necessary make a copy and modify it a little to remove such dependencies. 
    2. Write a new class to use JUnit to test several of the methods of this class.
    3. Deliverable: Upload your code to Github and do a Screencast showing you running it, explaining any interesting bits. Include links in your homework log.
  3. (Extra Credit) Follow along this presentation: Embrace Unit Testing
    1. Deliverable: Write a blog post explaining exactly what a Mock is, when you would use it, and what the role of the Mock is on the code on slide 35 of the presentation is. You will need to do a little google research in addition to following the presentation.

Learning Goals

  • Learn about Testing
    • What it is; why it is important; how we used to do it; automated testing
    • The different kinds of testing - Unit, Integration, System testing.
  • Tools used for automated testing
    • xUnit - e.g. jUnit. How it works, what the assertions are
    • What a test suite is
    • The red/green/refactor cycle
  • Tour of Eclipse features that support testing
    • Automatic running of unit testing
    • Refactoring commands
  • Test Driven Development
    • What it is, why it is important

Testing

  • Discussion: What is a bug? (http://xkcd.com/327/)
  • When you write a lot of code (100's, 1000's and 10K lines) you will have bugs, lots of bugs
  • Bugs come back (regressions)
  • Fixing one part can break another -- how do you find out? By running?
  • By the way, complementary skills are as important:
    • Learn to use the debugger - it is your friend!
    • Learn to use logging effectively. Sometimes it's the only solution
  • The role of a "spike" - plan to throw one out. Experiment. But then write good code
  • We used to have separate QA then QE departments. Write test plans. Do manual testing, logging lots of bugs that way
  • Nowadays there still is QA but they are much more integrated with the software engineers, sometimes there's no difference
  • Test automation is considered a requirement for serious software engineering.

Different Kinds of Testing

  • Unit testing: One 'unit' which usually means one class. Most easily and effectively automated
  • Integration Testing: Testing the integration of a set of classes or subsystem. Still automatable, but more difficult
  • System Testing: Most difficult to automate. Often involves 'simulated user'. But how do you deal with changes in UI?

Tools

  • Testing can be done without tools
  • JUnit is a simple tool to help you build suites of automated unit tests (in fact there are xUnit tools for many languages, as it is a pattern that has proven very successful.)
  • Classic agile process is: test - red - green - refactor

Lets look at some code

  1. Super simple case: junittest
  2. Look at Testing of Tim's model in JBS2011-PA3 (see pito branch)
  3. Look at my experimentation with the gameoflifemodel
  4. Eclipse tools:
    1. Running tests
    2. Refactoring

Test Driven Development

  • Principle is: write tests first, before writing the code!!!
  • Weird, eh?
  • Process
    • Write a test for the simplest case that could possibly work
    • Instead of testing a GameBoard that is (100,100) start with one that is (1,1) and test whether you can store a single object in it

  • Let's try a small case by hand. Look at MagicMath Class
    • Would like to have it do arithmetic on String values, e.g. "1" + "2" returns 3
    • And on words, e.g. "one" + "two" returns 3
    • Let's write the tests first
    • And now run them and fix the implementation
  • Let's add a feature to Tim's JBS2011-PA3 (see pito branch)
    • What feature should we add?
    • Write test first, now let's write implementation

Rules of thumb

  • Sometimes during testing you need to refactor the code or the test. This is good!
  • How to handle classes which depend on others?
    • First, it's good to avoid it if you can...
    • Mocks are classes which 'stand in' for other classes.
    • Take a look at Mockito
  • Test Fixtures 
    • Fancy term for objects (data) needed before the test is even attempted
    • The '@before' annotation is the simplest kind
    • Sometimes the fixture is a data file on disk, or a database
    • Note that tests MUST be independent of each other
    • More modern Junit's actually run the tests in random order!
  • Test Methods
    • Make the Test Name meaningful. Not test1() but testAddingStringToString()
    • Keep the test method as short as possible
    • Make sure the test method tests ONE thing
  • What to test
    • Minimal cases: 0 by 0, one object, zero length string
    • Typical cases
    • Extreme cases that should work
    • Other cases that should fail
    • Review the code and decide what else could be tested
  • Before fixing a  bug
    • Try to write a test that exercises the bug in isolation and add it to your test suite: RED
    • Now fix the bug: GREEN
    • If the bug ever comes back (regression) you will know!

SO: Try to get in the habit of writing even a few tests... It will pay off handsomely!




Videos from Class