Test Driven Development: Difference between revisions
(2 intermediate revisions by the same user not shown) | |||
Line 105: | Line 105: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
There are three types of dependency injection | |||
*Constructor injection (passed in the constructor and maybe an interface) | |||
*Property Injections (same as constructor but set on a property ) | |||
*Interface Injection (abstract class or interface implementation) | |||
In some languages functions a passed which, in their own right, are interfaces which support a given functionality. They are sometimes called Higher Order Functions. | |||
==Test Doubles== | |||
These are | |||
===Stubs=== | |||
Test stubs are fake objects with pre-programmed behavior ( Simulation of behaviour from other units ), Most of times they are simply returning fixed values. They are typically used for one of two reasons: | |||
===Mocks=== | |||
When most people talk about Mocks what they are actually referring to are Test Doubles. A Test Double is simply another object that conforms to the interface of the required Collaborator, and can be passed in its place. There are very few classes that operate entirely in isolation. Usually they need other classes or objects in order to function, whether injected via the constructor or passed in as method parameters. These are known as Collaborators or Depencies. | |||
===Fakes=== | |||
Fake objects have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example). The simplest way to think of a Fake is as a step up from a Stub. This means not only does it return values, but it also works just as a real Collaborator would. | |||
===Spies=== | |||
A test spy is an object that records its interaction with other objects throughout the code base. When deciding if a test was successful based on the state of available objects alone is not sufficient, we can use test spies and make assertions on things such as the number of calls, arguments passed to specific functions, return values and more.<br> | |||
<br> | |||
Test spies are useful to test both callbacks and how certain functions/methods are used throughout the system under test. The following simplified example shows how to use spies to test how a function handles a callback: | |||
=Gotchas= | |||
==Anti Patterns== | |||
*Make sure execution of tests order does not matter | |||
*Make sure you are testing what and not how | |||
*Make sure test cycles are efficient, long tests might mean too coupled | |||
==Limitations== | |||
*Does not eliminate defects | |||
*Need management support | |||
==Common Questions== | |||
*Does not need agile but more benefits, aimed at lowering maintenance costs | |||
*Do not need to write tests first | |||
*No right way |
Latest revision as of 05:53, 10 December 2020
Introduction
Costs
The cost of software according to this course was
Tests are split into three categories
- Does what was asked for
- Responds appropriately to bad input
- Acceptable Performance
Red Green Refactor
Start by writing tests with no code, write until test pass, refactor code. This is an iterative approach.
Benefits
- Requirements are verified by the tests
- Regression issues raised early
- Costs of maintenance is lowered
- Design first, when writing the tests first we are designing what they want
- Reduces over engineering
- Easy to know where you are in the project
Different Types of Testing
Types of Testing
- Unit Testing
- Functional Testing (UI/End-to-End)
- Integrating Testing
- User Acceptance Testing
Testing Approaches
- Black Box testing (testing the interface)
- White Box testing (testing internal aspects)
Tools
Some well known tools are
- Selenium
- Watir
- VS Coded UI
- Test Studio (Telerik)
- Silk Test (Micro Focus)
Terminology
- Test
- Test Suite (Group of tests)
- Before/After hooks to set up and tear down
- Assert, eg. isTrue, isNull, areEqual
- Test Execution
- Test Runner (async/sync)
Example Fizz Buzz
Requirements
This has the following requirements Given a positive number
- Divisible by 3 => "Fizz"
- Divisible by 5 => "Buzz"
- Divisible by 3 & 5 => "Fizz Buzz"
- Otherwise => Number
Step 1
Create initial test
private FizzBuzzService _fizzBuzzService;
public FizzBuzzTests() {
_fizzBuzzService = new FizzBuzzService();
}
[TestMethod]
public void ShouldPrintNumber() {
Assert.AreEqual("1", _fizzBuzzService.Print(1));
}
Step 2
So lets build out tests up as we go until we get to.
...
[TestMethod]
public void ShouldPrintFizz()
{
Assert.AreEqual("Fizz", _fizzBuzz.Print(3));
}
[TestMethod]
public void ShouldPrintBuzz()
{
Assert.AreEqual("Buzz", _fizzBuzz.Print(5));
Assert.AreEqual("Buzz", _fizzBuzz.Print(10));
}
[TestMethod]
public void ShouldPrintFizzBuzz()
{
Assert.AreEqual("FizzBuzz", _fizzBuzz.Print(15));
}
...
Techniques
Dependency Injection
This is used in Frameworks all the time.
The problem is that if we did not create a service and inject it but instead created in the class we are testing, it would be far harder to get the service to be in the correct state for the test. But if the service is passed in we could easily mock the state to do the test.
public class Greeter {
private NameService nameService;
public Greeter() {
this.nameService = new NamService()
}
public string SayHello() {
return $"Hello, {this.nameService.GetName()}";
}
}
There are three types of dependency injection
- Constructor injection (passed in the constructor and maybe an interface)
- Property Injections (same as constructor but set on a property )
- Interface Injection (abstract class or interface implementation)
In some languages functions a passed which, in their own right, are interfaces which support a given functionality. They are sometimes called Higher Order Functions.
Test Doubles
These are
Stubs
Test stubs are fake objects with pre-programmed behavior ( Simulation of behaviour from other units ), Most of times they are simply returning fixed values. They are typically used for one of two reasons:
Mocks
When most people talk about Mocks what they are actually referring to are Test Doubles. A Test Double is simply another object that conforms to the interface of the required Collaborator, and can be passed in its place. There are very few classes that operate entirely in isolation. Usually they need other classes or objects in order to function, whether injected via the constructor or passed in as method parameters. These are known as Collaborators or Depencies.
Fakes
Fake objects have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example). The simplest way to think of a Fake is as a step up from a Stub. This means not only does it return values, but it also works just as a real Collaborator would.
Spies
A test spy is an object that records its interaction with other objects throughout the code base. When deciding if a test was successful based on the state of available objects alone is not sufficient, we can use test spies and make assertions on things such as the number of calls, arguments passed to specific functions, return values and more.
Test spies are useful to test both callbacks and how certain functions/methods are used throughout the system under test. The following simplified example shows how to use spies to test how a function handles a callback:
Gotchas
Anti Patterns
- Make sure execution of tests order does not matter
- Make sure you are testing what and not how
- Make sure test cycles are efficient, long tests might mean too coupled
Limitations
- Does not eliminate defects
- Need management support
Common Questions
- Does not need agile but more benefits, aimed at lowering maintenance costs
- Do not need to write tests first
- No right way