Obstacle Driven Development: Extending Test Driven Development
Test Driven Development
-
Upload
milfont-consulting -
Category
Technology
-
view
1.684 -
download
0
Transcript of Test Driven Development
Test Driven Development [TDD]
Christiano Milfont#XPCE 2009, FortalezaCopyleft 2009 Milfont.org
Desenvolvimento guiado a testes
Test Driven Development
“Desenvolvimento guiado por testes é um caminho de gerenciamento
do medo durante a programação.”Kent Beck - Test Driven
Development by Example
Test Driven DevelopmentStandup Meeting @ 9h
Pair Up
Test First [Prática]
Code Refactor
Integrar ou Disponibilizar
Ir para casa @ 17h
Test Driven Development
O ritmo em 3 A’s• Arrange [Criar um objeto]• Act [Invocar um método]• Assert [Verificar o resultado]
Refactoring Workbook, Bill Wake
Test Driven Development
RED-GREEN-REFACTOR1.Escreva um teste que não funciona.2.Escreva o código e faço-o funcionar.3.Refatore e elimine o código repetitivo.
Test Driven Development
Red Bar Patterns• One Step Test• Starter Test• Explanation Test• Learning Test• Another Test• Regression Test• Break• Do Over
Test Driven Development
Red Bar Patterns• One Step Test• Starter Test• Explanation Test• Learning Test• Another Test• Regression Test• Break• Do Over
Issue issue = member.createIssue(name).withType(type).withLevel(level).withSummary(summary).toProject(project);
Test Driven Development
Red Bar Patterns• One Step Test• Starter Test• Explanation Test• Learning Test• Another Test• Regression Test• Break• Do Over
@Testpublic void createIssueFromMember()
throws IllegalArgumentIssueException {member = new Member();issue = member
.createIssue("Issue created");Assert.assertNotNull(
ISSUE_IN_NULL, issue);Assert.assertEquals(
"State is not unconfirmed",
Status.UNCONFIRMED, issue.getStatus());
}
Test Driven Development
Red Bar Patterns• One Step Test• Starter Test• Explanation Test• Learning Test• Another Test• Regression Test• Break• Do Over
issue = new Member()
.createIssue("Issue created");Assert.assertNotNull(
ISSUE_IN_NULL, issue);Assert.assertEquals(
"State is not unconfirmed",
Status.UNCONFIRMED, issue.getStatus());
Test Driven Development
Red Bar Patterns• One Step Test• Starter Test• Explanation Test• Learning Test• Another Test• Regression Test• Break• Do Over
type = new Type(){{this.setId(Long.valueOf(10));this.setName(BUG);
}};member = new Member().withType(type);issue = member.getIssueInProgress();Assert.assertNotNull(ISSUE_IN_NULL, issue);Assert.assertNotNull("Type is null",
issue.getType());Assert.assertTrue("Type is not BUG",
issue.getType().getId() == type.getId());Assert.assertTrue("Type is not BUG",
issue.getType().getName() == type.getName());Assert.assertEquals("Type is not BUG",
issue.getType().getName(), BUG);
Test Driven Development
Red Bar Patterns• One Step Test• Starter Test• Explanation Test• Learning Test• Another Test• Regression Test• Break• Do Over
@Testpublic void
createIssueFromMemberWithNameEmpty() {...}
@Test
public void setTypeInIssueFromMember() throws IllegalArgumentIssueException {
…}
Test Driven Development
Red Bar Patterns• One Step Test• Starter Test• Explanation Test• Learning Test• Another Test• Regression Test• Break• Do Over
Issue issue = member.createIssue(name).withType(type).withLevel(level).withSummary(summary).toProject(project);
Assert.assertNotNull("Issue não gerada com sucesso!",
issue);Assert.assertTrue("Issue não gerada e id não atribuído",
issue.getId() > 0);
Test Driven Development
Red Bar Patterns• One Step Test• Starter Test• Explanation Test• Learning Test• Another Test• Regression Test• Break• Do Over
@Testpublic void createIssueFromMemberWithNameNull() {
try {issue = new Member()
.createIssue(null);Assert.fail("Didn't find expected exception of type " +
IllegalArgumentIssueException.class.getName());} catch (IllegalArgumentIssueException e) {
Assert.assertEquals("Exception correctly catch",
"Name is null or empty“, e.getMessage());}
}
Test Driven Development
Red Bar Patterns• One Step Test• Starter Test• Explanation Test• Learning Test• Another Test• Regression Test• Break• Do Over
Test Driven Development
Green Bar Patterns• Fake It (‘till you make it)• Triangulate• Obvious Implementation• One to Many
Test Driven Development
Green Bar Patterns• Fake It (Till you make it)• Triangulate• Obvious Implementation• One to Many context.checking(new Expectations() {{
oneOf(repository).persist(with(any(Issue.class)));will(new CustomAction("Add id value to issue") {
public Object invoke(Invocation invocation)throws Throwable {( (Issue)
invocation.getParameter(0)).setId(Long.valueOf(1));
return null;}
});}});
Test Driven Development
Green Bar Patterns• Fake It (Till you make it)• Triangulate• Obvious Implementation• One to Many
@Testpublic void setNullSummaryInIssueFromMember() {...}@Test
public void setSummaryInIssueFromMember() {...}@Test
public void setEmptySummaryInIssueFromMember() { ..}
Test Driven Development
Green Bar Patterns• Fake It (Till you make it)• Triangulate• Obvious Implementation• One to Many ...
List<Issue> issues = new ArrayList<Issue>() {{
this.add(new Issue(Long.valueOf(134)));}
}...Assert.assertTrue(“blable”, issues.size()==1);
Test Driven Development
Green Bar Patterns• Fake It (Till you make it)• Triangulate• Obvious Implementation• One to Many ...
List<Issue> issues = new ArrayList<Issue>() {{
this.add(new Issue(Long.valueOf(134)));}
}...Assert.assertTrue(“blable”, issues.size()==1);
Test Driven Development
Testing Patterns• Child Test• Mock Object• Self Shunt• Log String• Crash Test Dummy• Broken Test• Clean Check-In
Test Driven Development
Testing Patterns• Child Test• Mock Object• Self Shunt• Log String• Crash Test Dummy• Broken Test• Clean Check-In
@RunWith(JMock.class)public class LifeCycleOfIssueInProjectTest { ... }
@RunWith(JMock.class)public class ReportIssuesTest { ... }
Test Driven Development
Testing Patterns• Child Test• Mock Object• Self Shunt• Log String• Crash Test Dummy• Broken Test• Clean Check-In
context.checking(new Expectations() {{oneOf(repository).persist(with(any(Issue.class)));will(new CustomAction("Add id value to issue") {
public Object invoke(Invocation invocation)throws Throwable {( (Issue)
invocation.getParameter(0)).setId(Long.valueOf(1));
return null;}
});}});
Test Driven Development
Testing Patterns• Child Test• Mock Object• Self Shunt• Log String• Crash Test Dummy• Broken Test• Clean Check-In
context.checking(new Expectations() {{oneOf(repository).persist(with(any(Issue.class)));will(new CustomAction("Add id value to issue") {
public Object invoke(Invocation invocation)throws Throwable {( (Issue)
invocation.getParameter(0)).setId(Long.valueOf(1));
repository.issues.add(
( (Issue) invocation.getParameter(0)));
return null;}
});}});...Assert.assertTrue(repository.size() == 12);
Test Driven Development
Testing Patterns• Child Test• Mock Object• Self Shunt• Log String• Crash Test Dummy• Broken Test• Clean Check-In
Test Driven Development
Testing Patterns• Child Test• Mock Object• Self Shunt• Log String• Crash Test Dummy• Broken Test• Clean Check-In
@Testpublic void createIssueFromMemberWithNameNull() {
try {issue = new Member()
.createIssue(null);Assert.fail("Didn't find expected exception of type " +
IllegalArgumentIssueException.class.getName());} catch (IllegalArgumentIssueException e) {
Assert.assertEquals("Exception correctly catch",
"Name is null or empty“, e.getMessage());}
}
Test Driven Development
Testing Patterns• Child Test• Mock Object• Self Shunt• Log String• Crash Test Dummy• Broken Test• Clean Check-In
Test Driven Development
Testing Patterns• Child Test• Mock Object• Self Shunt• Log String• Crash Test Dummy• Broken Test• Clean Check-In
Test Driven Development
Test Double• Dummy• Fake• Stubs• Spies• Mocks
Test Driven Development
Test Double• Dummy• Fake• Stubs• Spies• Mocks
...List<Issue> issues = new ArrayList<Issue>() {
{this.add(new
Issue(Long.valueOf(134)));}
}...Assert.assertTrue(“blable”, issues.size()==1);
Test Driven Development
Test Double• Dummy• Fake• Stubs• Spies• Mocks
...IssueRepository repository = new FakeRepository();List<Issue> issuesUnconfirmeds = repository.
getIssuesUnconfirmeds();Assert.assertTrue(“blable”, issuesUnconfirmeds !=
null);...public class FakeRepository implements
IssueRepository {public List<Issue> getIssuesUnconfirmeds() {
return new ArrayList<Issue>();}
}
Test Driven Development
Test Double• Dummy• Fake• Stubs• Spies• Mocks
context.checking(new Expectations() {{ignoring(repository).count();will(returnValue(42));
}});...Assert.assertEquals(12 , repository.count());
Test Driven Development
Test Double• Dummy• Fake• Stubs• Spies• Mocks
context.checking(new Expectations() {{oneOf(repository).persist(with(any(Issue.class)));will(new CustomAction("Add id value to issue") {
public Object invoke(Invocation invocation)throws Throwable {( (Issue)
invocation.getParameter(0)).setId(Long.valueOf(1));
repository.issues.add(
( (Issue) invocation.getParameter(0)));
return null;}
});}});...Assert.assertTrue(repository.size() == 12);
Test Driven Development
Test Double• Dummy• Fake• Stubs• Spies• Mocks
context.checking(new Expectations() {{oneOf(repository).persist(with(any(Issue.class)));will(new CustomAction("Add id value to issue") {
public Object invoke(Invocation invocation)throws Throwable {( (Issue)
invocation.getParameter(0)).setId(Long.valueOf(1));
return null;}
});}});
Test Driven Development
Fixture Setup• Setup• Tear Down
@Beforepublic void setUp() throws Exception {
Connection conn;try {
... IDatabaseConnection connection =
new DatabaseConnection(conn); DatabaseOperation.INSERT.execute(connection,
new FlatXmlDataSet(new FileInputStream( “issuetrackr.xml")));
conn.close();} catch (Exception exc) { ... }
}