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
- Write test
- Write code
- Refactor
BDD: Behaviour Driven Development
- Philosophy / Definition
- Focuses on clear understanding of software behavior from stakeholders
- Focuses on why code should be created: thinking "from the outside in"
- Extends TDD: tests written in natural language that non-programmers can read
- Can be used as Acceptance Tests
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
-
Unit & Integration Testing
-
BDD specific
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
- Setup (before all / BeforeClass)
- Runs once before any tests have run
- E.g. create database schema
- Test Fixture Setup (before each)
- Runs each time before any test
- E.g. clear & populate database / state
- Test (Test Fixture)
- Actual test to run: Assert something
- Test Fixture Teardown (after each)
- Runs each time after any test
- E.g. clear database / state
- 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);
}
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
- Available on many platforms
- Utilizes Gherkin syntax
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)
- Create .feature file (with many steps)
- 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
- Run tests and watch it fail
- Implement code specified in step definition to make test pass
- Run test to see step pass
- 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