Journey's diary developing a framework using tdd


Published on

From CBSoft 2012 Industry Trail

Published in: Technology
  • Be the first to comment

  • Be the first to like this

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Journey's diary developing a framework using tdd

  1. 1. Journeys Diary Developing a framework using TDD Eduardo Guerra
  2. 2. Case StudyThe Framework
  3. 3. + name conventions INTERFACE + anotations + entity class structure Query BuilderDynamicINTERFACE Proxy Framework
  4. 4. + name conventionsINTERFACE + anotations + entity class structure DSL
  5. 5. QueryBuilder JPA QueryBuilder MongoDB QueryBuilder Neo4JQueryBuilder Core QueryBuilder JDBC
  6. 6. For a goodunderstander, the method name is enough!
  7. 7. public List<Person>getPersonByNameOrAge (String name, int age); Using a simple namingpattern, you can define theentity and the properties to be used as filters.
  8. 8. public List<Person> getPersonByNameOrAge (String name, int age); The return type indicates if youexpect a single or multiple results. public Person getPersonByNameOrAge (String name, int age);
  9. 9. public List<Person>getPersonByNameOrAge (String name, int age); It is verified if theparameter types matches the property types.
  10. 10. public List<Order>getOrderPendingByDateGreater (Date date);Anotations or conventions canbe used to define the filter type.public List<Order>getOrderPendingByDate (@Greater Date date);
  11. 11. You can define new domain terms and use them on the method names.@DomainTerm(term=“pending“ conditions = @Condition( property=”status”, value=”P”))public List<Order>getOrderPendingByDate (@Greater Date date);
  12. 12. public List<Person> getPerson (@QueryObject PersonSearch p);For complex queries, you can define a class with the filters and metadataabout how they should be handled.
  13. 13. public List<Person> getPersonByNameAndLastName (@CompareToNull String name, @IgnoreWhenNull String lastname); You can configure thequery to compare to null or to ignore when the parameter is null.
  14. 14. Tests They consume mydevelopment time?
  15. 15. YESon the begining...
  16. 16. In the first tests, youusually need more effort tocreate scenarios and verifythe expect results.● Create mocks● Handle external resources● Do complex verifications
  17. 17. On the next tests, the code created is reused and the time to introduce a new testfor the TDD cycle is very small.
  18. 18. TipsPut common things in setupCreate helper methodsCreate test superclassesSearch for the right framework
  19. 19. QueryBuilder MethodParserSome MethodParser mockswere defined on setup andused on all tests.
  20. 20. QueryBuilder ClassMock FrameworkClassMock were used togenerate classes inruntime to test reflection.
  21. 21. To mock or not to mock?That is the question!
  22. 22. What should I do whenI have things that are hard to test, like external resources?MOCK
  23. 23. Why? It can make the test slow It will make the test difficult Test will be coupled with external APIs
  24. 24. But should I mock the external APIs themselves?MOCK
  25. 25. Why not? Create a class that encapsulates the access to this API! Decouple the class from the API It is a perfect match on the class needs The API can be hard to mock
  26. 26. What should I do whenI have classes that are not exposed to the class clients?MOCK
  27. 27. Why not? Test will be coupled to the solution The solution cant be refactored without changing the test Class dont need to be exposed
  28. 28. What should I do when myclass have a hotspot or adependence with variable behavior?MOCK
  29. 29. Why? Mock can be used to design the dependence API Mock can explore all possibilities, such possible errors Mock can be used to divide class responsibilities
  30. 30. Visitor that generates the query was mocked becauseQueryBuilder it is a hotspot. MOCK MethodParser MOCK A composite to store query parameters was not mocked because it is an internal solution.
  31. 31. Unit or Integration ?Can I use both on TDD?
  32. 32. Unit Test = decoupling Creating unit tests you aredividing responsibilities and defining the interaction among the classes.
  33. 33. Integration Test= boxblackblack boxYou are having feedback on yourimplementation, but it is nothelping to define your design.
  34. 34. If Im defining mydesign using tests, when can I useintegration tests?
  35. 35. Easy question! When yourdesign is already defined!
  36. 36. Class A Class B Class C Imagine that an architecture with these three classes
  37. 37. Developing Class A, the services neededfrom Class B were defined. Class A UNIT TEST MOCKClass C interface were defined on itsown TDD session. Class C UNIT TEST
  38. 38. Class A Class B Class C Now that everything is defined, you can use integration tests to develop Class BINTEGRATION TEST using TDD.
  39. 39. If you designed everything upfront, you dont need TDD as a design technique!
  40. 40. ESTED TQueryBuilder QueryBuilderSince the otherclasses are alreadytested, QueryExecutor QueryExecutorwas developed usingintegration tests. ESTED T QueryVisitor
  41. 41. Big RefactoringsThey will happen!
  42. 42. When you always search for the simplest solution, sometimes you reach a dead end!
  43. 43. However, most of the time theseproblems are concentrated on a single class and isolated from the others.
  44. 44. If that happens, STOP and refactor your solution!
  45. 45. method callQueryBuilder method call refactor store When appear a requirement process process where the processing depends on the next call... write query write query
  46. 46. Final ConsiderationsWhat ismissing?
  47. 47. You still have to know patterns tounderstand the solution that you aredriving through the tests.
  48. 48. You can use TDD only fordevelopment, or also as a design technique.If you choose design you can not avoid mocking!
  49. 49. Refactoring is a very important design tool!
  50. 50. Using TDD youfinish thesession veryproud of yourwork!
  51. 51. @Testpublic void presentationEnd(){ Presentation p = new Presentation(); Audience a = new Audience(); p.setAudience(a); p.perform(); p.end(); p.thanksEveryone(); assertTrue(a.isApplauding());}