Adopting TDD - by Don McGreal
- 1. © Improving Enterprises, Inc.
Applying Unit Tests &
Test-Driven Development
Don.McGreal@ImprovingEnterprises.com
@donmcgreal
linkedin.com/in/donmcgreal
- 2. © Improving Enterprises, Inc.
The Plan...
Unit Testing
Test Driven Development
Behavior Driven Development
Getting the most from your tests
Q&A
- 3. © Improving Enterprises, Inc.
The Plan...
Unit Testing
Test Driven Development
Behavior Driven Development
Getting the most from your tests
Q&A
- 4. © Improving Enterprises, Inc.
“I don’t want to touch that! It’ll
take forever, and I don’t know
what else will break if I do.
I’ll just rewrite it.”
Familiar?
- 5. © Improving Enterprises, Inc.
Unit Testing
Test the code quality
“Alarm System”
Regression testing
Reduce number of defects
Fix defects quicker
Confidence in the code
“Virtuous Cycle”
More Test
More Change
More Quality
More Confidence
CODE
- 6. © Improving Enterprises, Inc.
Unit Testing
What is a Unit?
What is a Test?
Smallest testable part of an application
Validation that the code is working properly
- 7. © Improving Enterprises, Inc.
Unit Testing - Traditional
public class MyClassTest {
[Test]
public void TestMethod1() {
MyClass instance = new MyClass();
instance.Method1();
Assert.AreEqual("expected", instance.Value);
}
[Test]
public void TestMethod2() {
MyClass instance = new MyClass();
Result result = instance.Method2();
Assert.IsNotNull(result);
Assert.AreEqual("expected", result.Value);
}
}
Exercise
Verify
Setup AreEqual(expected, actual);
AreNotEqual(expected, actual);
Greater(expected, actual);
Less(expected, actual);
IsFalse(condition);
IsTrue(condition);
IsNull(object);
IsNotNull(object);
IsEmpty(object);
AreSame(expected, actual);
AreNotSame(expected, actual);
Pass();
Fail();
Teardown
- 9. © Improving Enterprises, Inc.
The Plan...
Unit Testing
Test Driven Development
Behavior Driven Development
Getting the most from your tests
Q&A
- 10. © Improving Enterprises, Inc.
The Plan...
Unit Testing
Test Driven Development
Behavior Driven Development
Getting the most from your tests
Q&A
- 21. © Improving Enterprises, Inc.
Case Study
Empirical studies compared 4 projects, at Microsoft and IBM, that
used TDD with similar projects that did not use TDD.
The findings were similar to other case studies:
Defect
density
decreased
40%–90%
Development time
increased by 15–35%
(though teams agreed
that this was offset by
reduced maintenance
http://www.infoq.com/news/2009/03/TDD-Improves-Quality
- 23. © Improving Enterprises, Inc.
The Plan...
Unit Testing
Test Driven Development
Behavior Driven Development
Getting the most from your tests
Q&A
- 24. © Improving Enterprises, Inc.
The Plan...
Unit Testing
Test Driven Development
Behavior Driven Development
Getting the most from your tests
Q&A
- 25. © Improving Enterprises, Inc.
Unit Testing - Traditional
public class MyClassTest {
[Test]
public void TestMethod1() {
MyClass instance = new MyClass();
instance.Method1();
Assert.AreEqual("expected", instance.Value);
}
[Test]
public void TestMethod2() {
MyClass instance = new MyClass();
Result result = instance.Method2();
Assert.IsNotNull(result);
Assert.AreEqual("expected", result.Value);
}
}
Exercise
Verify
Setup AreEqual(expected, actual);
AreNotEqual(expected, actual);
Greater(expected, actual);
Less(expected, actual);
IsFalse(condition);
IsTrue(condition);
IsNull(object);
IsNotNull(object);
IsEmpty(object);
AreSame(expected, actual);
AreNotSame(expected, actual);
Pass();
Fail();
Teardown
- 26. © Improving Enterprises, Inc.
Unit Testing - BDD Style
public class WhenSystemIsInParticularState {
private MyClass instance;
[SetUp]
public void Init() {
instance = new MyClass();
}
[Test]
public void ShouldDoThisAndThat() {
instance.Method1();
Assert.AreEqual("expected", instance.Value);
}
[Test]
public void ShouldDoThatAndThis() {
Result result = instance.Method2();
Assert.IsNotNull(result);
Assert.AreEqual("expected", result.Value);
}
}
Setup
Exercise
Verify
assertEquals(expected, actual);
assertFalse(condition);
assertTrue(condition);
assertNull(object);
assertNotNull(object);
assertSame(expected, actual);
assertNotSame(unexpected, actual);
fail();
Teardown
- 27. © Improving Enterprises, Inc.
Unit Testing - BDD Style
public class WhenSystemIsInParticularState {
private MyClass instance;
[SetUp]
public void Init() {
instance = new MyClass();
}
[Test]
public void ShouldDoThisAndThat() {
instance.Method1();
Assert.AreEqual("expected", instance.Value);
}
[Test]
public void ShouldDoThatAndThis() {
Result result = instance.Method2();
Assert.IsNotNull(result);
Assert.AreEqual("expected", result.Value);
}
}
Setup
Exercise
Verify
assertEquals(expected, actual);
assertFalse(condition);
assertTrue(condition);
assertNull(object);
assertNotNull(object);
assertSame(expected, actual);
assertNotSame(unexpected, actual);
fail();
Teardown
- 28. © Improving Enterprises, Inc.
Behavior Driven Development
Forget about Tests; Think about Specifications
it’s easy to come up with reasons not to test, but writing
specs can become an integral part of development
Forget about Units; Think about Behaviors
worry more about how a developer will interact with the
code, and not what methods a class has
- 29. © Improving Enterprises, Inc.
BDD
BDD Frameworks for Java & .Net
• JBehave
• easyb (Groovy)
• NSpec
• nbehave
• others...
- 31. © Improving Enterprises, Inc.
The Plan...
Unit Testing
Test Driven Development
Behavior Driven Development
Getting the most from your tests
Q&A
- 32. © Improving Enterprises, Inc.
The Plan...
Unit Testing
Test Driven Development
Behavior Driven Development
Getting the most from your tests
Q&A
- 33. © Improving Enterprises, Inc.
The Problem
External dependencies affect
Performance
Portability
Stability
... of your tests.
Application
Remote
Application
Data
This is an opportunity and a driving force to design more
modular, more testable and more re-usable code.
- 34. © Improving Enterprises, Inc.
Integration Tests
Testing external connections to
other systems and databases
are acceptable, but not as part
of the general test suite.
These are called
Integration Tests
Application
Remote
Application
Data
- 35. © Improving Enterprises, Inc.
The Solution
ClientApp RemoteBank
debit(amt):boolean
credit(amt):boolean
SoaBankJmsBank FakeBank
Dependency Injection
bank
debit(amt):boolean
credit(amt):boolean
debit(amt):boolean
credit(amt):boolean
debit(amt):boolean
credit(amt):boolean
- 37. © Improving Enterprises, Inc.
Dummy Object
Null, "Ignored String", new Object()
public class ItemBehavior {
@Test
public void shouldCheckIfInventoryIsLow() {
Item item = new Item("name", 0.0, 10);
item.setQuantity(20);
assertFalse(item.isLowInventory());
item.setQuantity(2);
assertTrue(item.isLowInventory());
}
@Test
public void shouldStoreItemInformation() {
Item item = new Item("iPhone", 400.00, 10);
assertEquals("iPhone", item.getName());
assertEquals(400.00, item.getPrice());
assertEquals(10, item.getQuantity());
}
}
- 38. © Improving Enterprises, Inc.
Dummy Object
Null, "Ignored String", new Object()
public class ItemBehavior {
@Test
public void shouldCheckIfInventoryIsLow() {
Item item = new Item("name", 0.0, 10);
item.setQuantity(20);
assertFalse(item.isLowInventory());
item.setQuantity(2);
assertTrue(item.isLowInventory());
}
@Test
public void shouldStoreItemInformation() {
Item item = new Item("iPhone", 400.00, 10);
assertEquals("iPhone", item.getName());
assertEquals(400.00, item.getPrice());
assertEquals(10, item.getQuantity());
}
}
- 39. © Improving Enterprises, Inc.
Test Stub
Replace a real object with a test-specific object that
feeds the desired inputs into the system under test.
http://xunitpatterns.com/Test%20Stub.html
ClientApp app = new ClientApp();
RemoteBank bank = new FakeBank();
app.setBank(bank);
boolean success = app.debit(1000);
- 40. © Improving Enterprises, Inc.
Fake Object
Replace a component that the SUT depends on with a
much lighter-weight implementation.
http://xunitpatterns.com/Fake%20Object.html
ClientApp app = new ClientApp();
RemoteLogger log = new FakeLogger();
app.setLogging(log);
boolean success = app.debit(1000);
- 41. © Improving Enterprises, Inc.
Mock Object
http://xunitpatterns.com/Mock%20Object.html
Replace an object the SUT depends on with a test-
specific object that verifies it is being used correctly
by the SUT.
- 42. © Improving Enterprises, Inc.
Mock Object
http://xunitpatterns.com/Mock%20Object.html
public class MockLogger implements RemoteLogger{
public void logMessage(Date actualDate, String actualUser,
String actualActionCode, Object actualDetail) {
actualNumberCalls++;
Assert.assertEquals("date", expectedDate, actualDate);
Assert.assertEquals("user", expectedUser, actualUser);
Assert.assertEquals("action code", expectedActionCode, actualActionCode);
Assert.assertEquals("detail", expectedDetail, actualDetail);
}
}
A Mock Logger object:
ClientApp app = new ClientApp();
RemoteLogger log = new MockLogger();
app.setLogging(log);
boolean success = app.debit(1000);
- 43. © Improving Enterprises, Inc.
The Plan...
Unit Testing
Test Driven Development
Behavior Driven Development
Getting the most from your tests
Q&A
- 44. © Improving Enterprises, Inc.
The Plan...
Unit Testing
Test Driven Development
Behavior Driven Development
Getting the most from your tests
Q&A
- 45. © Improving Enterprises, Inc.
THANK YOU!
Don.McGreal@ImprovingEnterprises.com
@donmcgreal
linkedin.com/in/donmcgreal
- 48. www.synerzip.com39 3939
Synerzip in a Nut-shell
1. Software product development partner for small/mid-sized
technology companies
• Exclusive focus on small/mid-sized technology companies
• By definition, all Synerzip work is the IP of its respective clients
• Deep experience in full SDLC – design, dev, QA/testing, deployment
• Technology and industry domain agnostic
www.synerzip.com
- 49. www.synerzip.com39 3939
Synerzip in a Nut-shell
1. Software product development partner for small/mid-sized
technology companies
• Exclusive focus on small/mid-sized technology companies
• By definition, all Synerzip work is the IP of its respective clients
• Deep experience in full SDLC – design, dev, QA/testing, deployment
• Technology and industry domain agnostic
2. Dedicated team of high caliber software professionals
• Seamlessly extends client’s local team, offering full transparency
• NOT just “staff augmentation”, but provide full mgmt support
www.synerzip.com
- 50. www.synerzip.com39 3939
Synerzip in a Nut-shell
1. Software product development partner for small/mid-sized
technology companies
• Exclusive focus on small/mid-sized technology companies
• By definition, all Synerzip work is the IP of its respective clients
• Deep experience in full SDLC – design, dev, QA/testing, deployment
• Technology and industry domain agnostic
2. Dedicated team of high caliber software professionals
• Seamlessly extends client’s local team, offering full transparency
• NOT just “staff augmentation”, but provide full mgmt support
3. Actually reduces risk of development/delivery
• Experienced team - uses appropriate level of engineering discipline
• Practices Agile development – responsive, yet disciplined
www.synerzip.com
- 51. www.synerzip.com39 3939
Synerzip in a Nut-shell
1. Software product development partner for small/mid-sized
technology companies
• Exclusive focus on small/mid-sized technology companies
• By definition, all Synerzip work is the IP of its respective clients
• Deep experience in full SDLC – design, dev, QA/testing, deployment
• Technology and industry domain agnostic
2. Dedicated team of high caliber software professionals
• Seamlessly extends client’s local team, offering full transparency
• NOT just “staff augmentation”, but provide full mgmt support
3. Actually reduces risk of development/delivery
• Experienced team - uses appropriate level of engineering discipline
• Practices Agile development – responsive, yet disciplined
4. Reduces cost – dual-shore team, 50% cost advantage
www.synerzip.com
- 52. www.synerzip.com39 3939
Synerzip in a Nut-shell
1. Software product development partner for small/mid-sized
technology companies
• Exclusive focus on small/mid-sized technology companies
• By definition, all Synerzip work is the IP of its respective clients
• Deep experience in full SDLC – design, dev, QA/testing, deployment
• Technology and industry domain agnostic
2. Dedicated team of high caliber software professionals
• Seamlessly extends client’s local team, offering full transparency
• NOT just “staff augmentation”, but provide full mgmt support
3. Actually reduces risk of development/delivery
• Experienced team - uses appropriate level of engineering discipline
• Practices Agile development – responsive, yet disciplined
4. Reduces cost – dual-shore team, 50% cost advantage
5. Offers long term flexibility – allows (facilitates) taking
offshore team captive – aka “BOT” option
www.synerzip.com