Test Driven Development

34
Test Driven Development [TDD] Christiano Milfont #XPCE 2009, Fortaleza Copyleft 2009 Milfont.org Desenvolvimento guiado a testes

Transcript of Test Driven Development

Page 1: Test Driven Development

Test Driven Development [TDD]

Christiano Milfont#XPCE 2009, FortalezaCopyleft 2009 Milfont.org

Desenvolvimento guiado a testes

Page 2: Test Driven Development

Test Driven Development

“Desenvolvimento guiado por testes é um caminho de gerenciamento

do medo durante a programação.”Kent Beck - Test Driven

Development by Example

Page 3: Test Driven Development

Test Driven DevelopmentStandup Meeting @ 9h

Pair Up

Test First [Prática]

Code Refactor

Integrar ou Disponibilizar

Ir para casa @ 17h

Page 4: Test Driven Development

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

Page 5: Test Driven Development

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.

Page 6: Test Driven Development

Test Driven Development

Red Bar Patterns• One Step Test• Starter Test• Explanation Test• Learning Test• Another Test• Regression Test• Break• Do Over

Page 7: Test Driven Development

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);

Page 8: Test Driven Development

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());

}

Page 9: Test Driven Development

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());

Page 10: Test Driven Development

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);

Page 11: Test Driven Development

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 {

…}

Page 12: Test Driven Development

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);

Page 13: Test Driven Development

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());}

}

Page 14: Test Driven Development

Test Driven Development

Red Bar Patterns• One Step Test• Starter Test• Explanation Test• Learning Test• Another Test• Regression Test• Break• Do Over

Page 15: Test Driven Development

Test Driven Development

Green Bar Patterns• Fake It (‘till you make it)• Triangulate• Obvious Implementation• One to Many

Page 16: Test Driven Development

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;}

});}});

Page 17: Test Driven Development

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() { ..}

Page 18: Test Driven Development

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);

Page 19: Test Driven Development

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);

Page 20: Test Driven Development

Test Driven Development

Testing Patterns• Child Test• Mock Object• Self Shunt• Log String• Crash Test Dummy• Broken Test• Clean Check-In

Page 21: Test Driven Development

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 { ... }

Page 22: Test Driven Development

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;}

});}});

Page 23: Test Driven Development

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);

Page 24: Test Driven Development

Test Driven Development

Testing Patterns• Child Test• Mock Object• Self Shunt• Log String• Crash Test Dummy• Broken Test• Clean Check-In

Page 25: Test Driven Development

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());}

}

Page 26: Test Driven Development

Test Driven Development

Testing Patterns• Child Test• Mock Object• Self Shunt• Log String• Crash Test Dummy• Broken Test• Clean Check-In

Page 27: Test Driven Development

Test Driven Development

Testing Patterns• Child Test• Mock Object• Self Shunt• Log String• Crash Test Dummy• Broken Test• Clean Check-In

Page 28: Test Driven Development

Test Driven Development

Test Double• Dummy• Fake• Stubs• Spies• Mocks

Page 29: Test Driven Development

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);

Page 30: Test Driven Development

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>();}

}

Page 31: Test Driven Development

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());

Page 32: Test Driven Development

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);

Page 33: Test Driven Development

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;}

});}});

Page 34: Test Driven Development

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) { ... }

}