Testing: TDD, BDD, WTH?

Timothy Lim / @thewheat
Slides: http://thewheat.github.io/presentation-testing-tdd-bdd-wth

Tests: Not just the thing you did in school

  • What is Testing To You?
    • Ensuring code does what it is meant to do
    • Ensuring system works as expected
    • Being able to manually test things
  • What is your current testing strategy?
    • Code and hope it works?
    • Code locally, test, push to production and retest?
    • Staging Environments?
  • Are you confident in your build?

TDD: Test Driven Development

  1. Write test
  2. Write code
  3. Refactor

BDD: Behaviour Driven Development

Different types of tests

  • There are many but will focus on 3
  • Unit Tests
    • Testing core unit of works
    • Isolated: no interaction with other systems (e.g. databases, web services)
  • Integration Tests
    • Test the integration between 2 different "units" / systems (e.g. your core system and the database / web service)
    • Database interaction: test database or in-memory databses (H2 / SQLite)
  • Functional Tests

Where to Start?

Functional Tests Integration Tests Unit Tests
Big picture Small picture
More Complex Simple
Less Robust Robust
Slow Fast

Test Suites / Frameworks

Structure of Testing Frameworks

Setup (before all / BeforeClass) Runs once before any tests have run Create DB schema
Teardown (after all / AfterClass) Runs once after all tests are run Drop DB schema
Test (Test Fixture) Actual test to run Assert something
Test Fixture Setup (before each) Runs each time before any test (i.e. runs 2 times if there are 2 tests) Populate DB / state
Test Fixture Teardown (after each) Runs each time after any test Clear DB / state

Structure of Testing Functions

  1. Setup (before all / BeforeClass)
    • Runs once before any tests have run
    • E.g. create database schema
  2. Test Fixture Setup (before each)
    • Runs each time before any test
    • E.g. clear & populate database / state
  3. Test (Test Fixture)
    • Actual test to run: Assert something
  4. Test Fixture Teardown (after each)
    • Runs each time after any test
    • E.g. clear database / state
  5. Teardown (after all / AfterClass)
    • Runs once after all tests are run
    • E.g. drop database schema

Testing Concepts (1/3)

  • Test (Test Fixture)
    • Actual test to run
    • Assert something
    @Test
    addTwoPositiveNumbers(){
        calc = new Calculator();
        output = calc.add(1,2);
        Assert.Equal(3, output);
    }
    
    @Test
    primeNumberIsCorrectlyDetected(){
        calc = new Calculator();
        output = calc.isPrime(2);
        Assert.IsTrue(output);
    }
    

Testing Concepts (2/3)

Testing Concepts (3/3)

  • Mocks
    • Simulated objects that mimic the behavior of real objects
    • Steps:
      1. Create a mock object
      2. Define behaviour
      3. Call or test behaviour
      // mock a concrete class
      LinkedList mockedList = mock(LinkedList.class); 
      
      //stubbing - before execution
      when(mockedList.get(0)).thenReturn("first");
      
      //folloing princs "first"
      System.out.println(mockedList.get(0));
      
      //following prints "null" because get(999) as not stubbed
      System.out.println(mockedList.get(999)); 
      
      // Source: Mockito 
                                          

Functional Testing Concepts

  • Page Object Pattern
    • A pattern that:
      • reduces code duplication
      • makes tests more readable and robust
      • makes tests more maintanable
    • They represent the services offered by a particular page
          i.e. models the 'page' for your test to interact with
    • They should be the only thing that has a deep knowledge of the structure of the HTML of a page
          i.e. changes to interface / platform (e.g. web to native), should only affect page object: other parts of tests stay the same

Functional Testing Concepts with Cucumber (1/3)

Cucumber lets software development teams describe how software should behave in plain text

Functional Testing Concepts with Cucumber (2/3)

     1: Feature: Some terse yet descriptive text of what is desired
     2:   Textual description of the business value of this feature
     3:   Business rules that govern the scope of the feature
     4:   Any additional info that will make the feature easier to understand
     5: 
     6:   Scenario: Some determinable business situation
     7:     Given some precondition
     8:       And some other precondition
     9:      When some action by the actor
    10:       And some other action
    12:      Then some testable outcome is achieved
    13:       And something else we can check happens too
    14: 
    15:   Scenario: A different situation
    16:       ...    
    

Functional Testing Concepts with Cucumber (3/3)

  1. Create .feature file (with many steps)
  2. Write a single step definition
    • Convert readable text to actual code / interactions
    • With the correct plugins: Ctrl+Click step in .feature file to set up the function
  3. Run tests and watch it fail
  4. Implement code specified in step definition to make test pass
  5. Run test to see step pass
  6. Repeat 2-5 until all steps in .feature file implemented

Things to note

  • Browser tests
    • Beware the ajax loads and templates
    • sleep() if you must, but it's not ideal: implicitlyWait() could be the answer
    • Different environments respond differently on the same hardware
  • Code Coverage
  • Testing is not the end all and be all

In conclusion

  • Testing is great
  • Helps speed development
  • Helps ensure that your code works
  • Peace of mind while refactoring

THE END

Timothy Lim / @thewheat
http://thewheat.github.io/presentation-testing-tdd-bdd-wth