Testing and Testable Code
Upcoming SlideShare
Loading in...5
×
 

Testing and Testable Code

on

  • 3,934 views

About Test Driven Development, Testing and Testable Code. So really simply about... design

About Test Driven Development, Testing and Testable Code. So really simply about... design

Statistics

Views

Total Views
3,934
Views on SlideShare
3,335
Embed Views
599

Actions

Likes
8
Downloads
140
Comments
0

6 Embeds 599

http://paulszulc.wordpress.com 575
http://www.linkedin.com 8
https://www.linkedin.com 8
http://www.slideshare.net 6
http://translate.googleusercontent.com 1
http://webcache.googleusercontent.com 1

Accessibility

Categories

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Testing and Testable Code Testing and Testable Code Presentation Transcript

  • Testing and Testable code Paweł Szulc http://paulszulc.wordpress.com [email_address]
  • Testing and testable code
    • Who am I?
      • Paweł Szulc
        • Former Sun Campus Ambassador
        • Java Developer (currently Wicket+Spring+JPA)
        • Agile Enthusiast
      • Blog: http://paulszulc.wordpress.com
      • E-mail: paul.szulc@gmail.com
  • Testing and testable code
    • What are we going to talk about?
  • Testing and testable code
    • What are we going to talk about?
      • Test Driven Development
  • Testing and testable code
    • What are we going to talk about?
      • Test Driven Development
      • Testing
  • Testing and testable code
    • What are we going to talk about?
      • Test Driven Development
      • Testing
      • Testable code
  • Testing and testable code
    • What are we going to talk about?
      • Test Driven Development
      • Testing
      • Testable code
    • So of course, we are going to talk about...
  • Testing and testable code
    • What are we going to talk about?
      • Test Driven Development
      • Testing
      • Testable code
    • So of course, we are going to talk about...
    DESIGN
  • Testing and testable code
    • What are we going to talk about?
      • Test Driven Development
      • Testing
      • Testable code
    • So of course, we are going to talk about...
    DESIGN controversial?
  • Testing and testable code
    • The ultimate conference question
  • Testing and testable code
    • The ultimate conference question
  • Testing and testable code
    • The ultimate conference question
  • Testing and testable code
    • The ultimate conference question
      • Paradox?
  • Testing and testable code
    • The ultimate conference question
      • Paradox?
      • After-party conclusion
        • TDD is good because I have large set of tests in my application
        • I don't use TDD because
          • Code to complex
          • Code not maintainable – twice more effort
  • Testing and testable code
    • The ultimate conference question
      • Paradox?
      • After-party conclusion
        • TDD is good because I have large set of tests in my application
        • I don't use TDD because
          • Code to complex
          • Code not maintainable – twice more effort
      • Paradox? No. Misunderstanding? Yes!
  • Testing and testable code
    • Test Driven Development
  • Testing and testable code
    • Test Driven Development
      • Really bad name
  • Testing and testable code
    • Test Driven Development
      • Really bad name
      • It's not about testing, it's about requirements and design
  • Testing and testable code
    • Test Driven Development
      • Really bad name
      • It's not about testing, it's about requirements and design
      • Large tests and relatively high coverage are just positive side effects
  • Testing and testable code
    • Test Driven Development
      • Two pitfalls when doing TDD
        • TDD Prophet
        • TDD Architect
  • Testing and testable code
    • Test Driven Development
      • Two pitfalls when doing TDD
        • TDD Prophet
        • TDD Architect
    ” Test Driven Development is like sex. If you don't like it, you probably ain't doing it right.”
  • Testing and testable code
    • Example:
      • Requirement: create login page
  • Testing and testable code
    • Example:
      • Requirement: create login page
        • Should log in for correct login and password
        • Should not login for incorrect login
        • Should not login for incorrect password
        • Not logged in user is an 'guest user'
        • Guest user has login 'Guest'
  • Testing and testable code
    • Pitfall #1: TDD Prophet
  • Testing and testable code
    • Pitfall #1: TDD Prophet
      • Ok, let me see, what I got here...
        • Should log in for correct login and pas..
        • Should not login fo...
  • Testing and testable code
    • Pitfall #1: TDD Prophet
      • Ok, let me see, what I got here...
        • Should log in for correct login and pas..
        • Should not login fo...
      • Ok, right so definitely what I need for start is ...
  • Testing and testable code
    • Pitfall #1: TDD Prophet
      • Ok, let me see, what I got here...
        • Should log in for correct login and pas..
        • Should not login fo...
      • Ok, right so definitely what I need for start is ...
        • I need User domain class!
  • Testing and testable code
    • Pitfall #1: TDD Prophet
      • Ok, let me see, what I got here...
        • Should log in for correct login and pas..
        • Should not login fo...
      • Ok, right so definitely what I need for start is ...
        • I need User domain class!
        • User need to have login and password fields
  • Testing and testable code
    • Pitfall #1: TDD Prophet
      • Ok, let me see, what I got here...
        • Should log in for correct login and pas..
        • Should not login fo...
      • Ok, right so definitely what I need for start is ...
        • I need User domain class!
        • User need to have login and password fields
        • Getters and setters!
  • Testing and testable code
    • Pitfall #1: TDD Prophet
      • Ok, let me see, what I got here...
        • Should log in for correct login and pas..
        • Should not login fo...
      • Ok, right so definitely what I need for start is ...
        • I need User domain class!
        • User need to have login and password fields
        • Getters and setters!
        • Equals and hashCode methods for equality
  • Testing and testable code
    • Pitfall #1: TDD Prophet
      • Ok, let me see, what I got here...
        • Should log in for correct login and pas..
        • Should not login fo...
      • Ok, right so definitely what I need for start is ...
        • I need User domain class!
        • User need to have login and password fields
        • Getters and setters!
        • Equals and hashCode methods for equality
      • … and so tests writing begins
  • Testing and testable code @Test public void testUserCreation() throws Exception { User user = new User(); }
  • Testing and testable code @Test public void testUserHasLoginAndPassword() throws Exception { User user = new User(); user.setLogin("login"); user.setPassword("password"); assertEquals("login", user.getLogin()); assertEquals("password", user.getPassword()); }
  • Testing and testable code @Test public void testEqualsMethodValidForSameLogin() throws Exception { User user1 = new User(); user1.setLogin("login"); User user2 = new User(); user2.setLogin("login"); assertEquals(user1, user2); }
  • Testing and testable code @Test public void testEqualsMethodReturnsFalseForDifferentLogin() throws Exception { User user1 = new User(); user1.setLogin("login"); User user2 = new User(); user2.setLogin("login2"); assertFalse(user1.equals(user2)); }
  • Testing and testable code @Test public void testEqualsHashCodeConstract() throws Exception { User user1 = new User(); user1.setLogin("login"); User user2 = new User(); user2.setLogin("login"); assertTrue(user1.equals(user2)); assertEquals(user1.hashCode(),user2.hashCode()); }
  • Testing and testable code public class User { private String login, password; public User() { } public String getLogin() { return login; } public void setLogin(String login) { this.login = login; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (!login.equals(user.login)) return false; return true; } public int hashCode() { return login.hashCode(); } } Design you get:
  • Testing and testable code
    • Example:
      • Requirement: create login page
        • Should log in for correct login and password
        • Should not login for incorrect login
        • Should not login for incorrect password
        • Not logged in user is an 'guest user'
        • Guest user has login 'Guest'
  • Testing and testable code
    • Example:
      • Requirement: create login page
        • Should log in for correct login and password
        • Should not login for incorrect login
        • Should not login for incorrect password
        • Not logged in user is an 'guest user'
        • Guest user has login 'Guest'
  • Testing and testable code … the test should really looked like this: @Test public void shouldLoginForCorrectLoginAndPassword() throws Exception{ // given String login = "login"; String password = "password"; dao.persist(new User(login,password)); // when User user = service.logIn(login, password); // then assertEquals(login, user.getLogin()); assertEquals(password, user.getPassword()); }
  • Testing and testable code public class User { private String login, password; public User(String login, String password) { this.login = login; this.password = password; } public String getLogin() { return login; } public String getPassword() { return password; } } Design you get:
  • Testing and testable code public class User { private String login, password; public User() { } public String getLogin() { return login; } public void setLogin(String login) { this.login = login; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (!login.equals(user.login)) return false; return true; } public int hashCode() { return login.hashCode(); } } public class User { private String login, password; public User(String login, String password) { this.login = login; this.password = password; } public String getLogin() { return login; } public String getPassword() { return password; } }
  • Testing and testable code
    • Pitfall #1: TDD Prophet – consequences
      • Code:
        • You are stuck with huge test base and an implementation that you might never need
        • Smallest change in your code make a lot of tests fail, even if that change isn't caused be change of requirements
        • Some of the code might never be used. Ever!
      • Design
        • Not focusing on requirements
        • Created design based on experience only.
        • Design is complex, not maintainable
  • Testing and testable code
    • Test Driven Design is about
  • Testing and testable code
    • Test Driven Design is about
      • Requirements
        • Implement only what the client wants
  • Testing and testable code
    • Test Driven Design is about
      • Requirements
        • Implement only what the client wants
      • Design
        • Smallest design that does the job right
  • Testing and testable code
    • Just because you are writing tests before implementation, does not mean you are using TDD practice.
  • Testing and testable code
    • Just because you are writing tests before implementation, does not mean you are using TDD practice.
    • Symptoms of being TDD Prophet:
      • Testing getters and setters
      • Asking questions on Internet like:
        • Should I test private methods?
        • Is 75% code coverage good enough?
  • Testing and testable code
    • Pitfall #2: TDD Architect
  • Testing and testable code
    • Pitfall #2: TDD Architect
      • Gather all requirements
  • Testing and testable code
    • Pitfall #2: TDD Architect
      • Gather all requirements
      • Create basic architecture using interfaces
  • Testing and testable code
    • Pitfall #2: TDD Architect
      • Gather all requirements
      • Create basic architecture using interfaces
      • Start writing tests while implementing previously designed interfaces
  • Testing and testable code
    • Pitfall #2: TDD Architect - consequences
      • Just complexed variation of TDD Prophet
  • Testing and testable code
    • Pitfall #2: TDD Architect - consequences
      • Just complexed variation of TDD Prophet
      • Bigger chances that code will do what client wants (requirements)
      • Will not stand a chance when the requirements change (design)
  • Testing and testable code
    • Pitfall #2: TDD Architect - consequences
      • Just complexed variation of TDD Prophet
      • Bigger chances that code will do what client wants (requirements)
      • Will not stand a chance when the requirements change (design)
      • Again: not a TDD practice!
  • Testing and testable code
    • So what is TDD practice?
  • Testing and testable code
    • So what is TDD practice – the idea:
      • Add test
      • Run all tests and see the new one failing
      • Add some code
      • Run all tests and see the new one succeeds
      • Refactor
  • Testing and testable code
    • So what is TDD practice – the idea enhanced:
      • Pick up a requirement
      • Add test
      • Run all tests and see the new one failing
      • Add some code
      • Run all tests and see the new one succeeds
      • Refactor
  • Testing and testable code
    • So what is TDD practice – the idea enhanced:
      • Pick up a requirement
      • Add test that represents the requirement
      • Run all tests and see the new one failing
      • Add some code
      • Run all tests and see the new one succeeds
      • Refactor
  • Testing and testable code
    • So what is TDD practice – the idea enhanced:
      • Pick up a requirement
      • Add test that represents the requirement
      • Run all tests and see the new one failing
      • Add some code
      • Run all tests and see the new one succeeds
      • Refactor whenever design is getting ugly
  • Testing and testable code
    • So what is TDD practice – the idea enhanced:
      • Pick up a requirement
      • Add test that represents the requirement
      • Run all tests and see the new one failing
      • Add some code
      • Run all tests and see the new one succeeds
      • Refactor whenever design is getting ugly
    • You start with requirement, you end up with design!
  • Testing and testable code
    • Test Driven Development
      • Really bad name
      • It's not about testing, it's about requirements and design
      • Large tests and relatively high coverage are just positive side effects
  • Testing and testable code
    • Test Driven Development
      • Really bad name
        • Test Driven Design
        • Requirements Driven Design
      • It's not about testing, it's about requirements and design
      • Large tests and relatively high coverage are just positive side effects
  • Testing and testable code
    • Test Driven Development
      • Really bad name
        • Test Driven Design
        • Requirements Driven Design
      • It's not about testing, it's about requirements and design
        • Tests are simply translation of requirements into code language
      • Large tests and relatively high coverage are just positive side effects
  • Testing and testable code The BIG Problem...
  • Testing and testable code The BIG Problem... You still simply ain't gonna use TDD.
  • Testing and testable code The BIG Problem... You still simply ain't gonna use TDD. … whatever the reasons are.
  • Testing and testable code
    • The Big Problem
      • ” Test Driven Development is like riding a bike”
    – Misko Hevery,GeeCON2009
  • Testing and testable code
    • The Big Problem
      • ” Test Driven Development is like riding a bike”
    – Misko Hevery,GeeCON2009
    • How to start riding that bike?
  • Testing and testable code
    • The Big Problem
      • ” Test Driven Development is like riding a bike”
    – Misko Hevery,GeeCON2009
    • How to start riding that bike?
      • TDD small app
  • Testing and testable code
    • The Big Problem
      • ” Test Driven Development is like riding a bike”
    – Misko Hevery,GeeCON2009
    • How to start riding that bike?
      • TDD small app
      • Bugs Driven Tests
  • Testing and testable code
    • Bugs Driven Tests
  • Testing and testable code
    • Bugs Driven Tests
      • Pick up a bug
  • Testing and testable code
    • Bugs Driven Tests
      • Pick up a bug
      • Write test that checks whether the bug is fixed
  • Testing and testable code
    • Bugs Driven Tests
      • Pick up a bug
      • Write test that checks whether th bug is fixed
      • Test should fail
  • Testing and testable code
    • Bugs Driven Tests
      • Pick up a bug
      • Write test that checks whether th bug is fixed
      • Test should fail
      • Fix the bug
  • Testing and testable code
    • Bugs Driven Tests
      • Pick up a bug
      • Write test that checks whether th bug is fixed
      • Test should fail
      • Fix the bug
      • Test should succeed
  • Testing and testable code
    • Bugs Driven Tests – pros
      • Obvious
        • You know your bug is fixed when your test passes.
        • No bugs regression
  • Testing and testable code
    • Bugs Driven Tests – pros
      • Obvious
        • You know your bug is fixed when your test passes.
        • No bugs regression
      • Cognitive
        • You start writing tests. It becomes something natural.
        • Rule 80:20
          • 20% code tested
          • 80% of importance
  • Testing and testable code
    • Bugs Driven Tests – cons
      • I just can't!
        • ” I would really like to write test for this implementation. But I just simply don't know how!”
  • Testing and testable code
    • Bugs Driven Tests – cons
      • I just can't!
        • ” I would really like to write test for this implementation. But I just simply don't know how!”
      • Example:
        • Library – the ultimate University example :)
  • Testing and testable code
    • Bugs Driven Tests – cons
    public class Library { private BookSearch bookSearch; public Library() { bookSearch = new BookSearch(); } public boolean addReader(Reader r) { ... } }
  • Testing and testable code
    • Bugs Driven Tests – cons
    public class Library { private BookSearch bookSearch; public Library() { bookSearch = new BookSearch(); } public boolean addReader(Reader r) { ... } }
  • Testing and testable code
    • Bugs Driven Tests – cons
    public class BookSearch { public BookSearch() { DBConnection.init(); } }
  • Testing and testable code
    • Bugs Driven Tests – cons
      • Problem, because you write your test AFTER the implementation
      • Code might be not testable and so writing tests hard or even impossible
  • Testing and testable code
    • Testable code
  • Testing and testable code
    • Testable code
      • Misko Hevery ( http://misko.hevery.com )
  • Testing and testable code
    • Testable code
      • Misko Hevery ( http://misko.hevery.com )
    • Misko Hevery and gruppies
  • Testing and testable code
    • Testable code
  • Testing and testable code
    • Testable code
      • Makes testing light and simple activity
  • Testing and testable code
    • Testable code
      • Makes testing light and simple activity
      • Promotes good design and good quality code
  • Testing and testable code
    • Testable code
      • Makes testing light and simple activity
      • Promotes good design and good quality code
      • Declarative
  • Testing and testable code
    • Testable code
      • Makes testing light and simple activity
      • Promotes good design and good quality code
      • Declarative
      • Easy to read
  • Testing and testable code
    • Testable code
      • Makes testing light and simple activity
      • Promotes good design and good quality code
      • Declarative
      • Easy to read
      • Easy to maintain
  • Testing and testable code
    • Global state
      • Good or Bad?
  • Testing and testable code
    • Global state
    int a = new Foo().bar(); int b = new Foo().bar(); Does: a == b or a !=b
  • Testing and testable code
    • Global state
    Insanity noun ” Repeating the same thing and expecting a different result.”
  • Testing and testable code
    • Global state
  • Testing and testable code
    • Global state
  • Testing and testable code
    • Global state
  • Testing and testable code
    • Global state
  • Testing and testable code
    • Global state – root problem: globally accessible state
      • Example:
        • Class A and class B
        • A and B does not know anything about each other
        • Both states depends on global variable
          • static int count;
  • Testing and testable code
    • Global state – root problem: globally accessible state
      • Why problem?
        • Developers need to read every single line of code to understand the implementation
        • Test are not isolated, even if they look like they are
    ” You may not have thought of it this way before, but whenever you use static state, you’re creating secret communication channels and not making them clear in the API.”
  • Testing and testable code
    • Global state – root problem: globally accessible state
      • Why problem?
        • Every test using global state needs it to start in an expected state, or the test will fail.
        • Global state often prevents tests from being able to run in parallel
  • Testing and testable code
    • Singletons
      • Good or bad?
  • Testing and testable code
    • Singletons
      • Singletons are global state!
        • Gang Of Four singletons
          • Private constructor
          • Static method instantiating
  • Testing and testable code
    • Singletons
      • Singletons are global state!
        • Gang Of Four singletons
          • Private constructor
          • Static method instantiating
      • Same situation: class A and B both hold reference to singleton C affect each other state
  • Testing and testable code
    • Singletons
      • Singletons are global state!
        • Gang Of Four singletons
          • Private constructor
          • Static method instantiating
      • Same situation: class A and B both hold reference to singleton C affect each other state
      • Only exception: no state (rarely happens)
  • Testing and testable code
    • Singletons
      • Singletons are global state!
        • Gang Of Four singletons
          • Private constructor
          • Static method instantiating
      • Same situation: class A and B both hold reference to singleton C affect each other state
      • Only exception: no state (rarely happens)
      • Tests: methods like reset()
  • Testing and testable code
    • Main problem with global states (inclugin singletons)
      • They are liars
  • Testing and testable code
    • Main problem with global states (inclugin singletons)
      • They are liars
      • They hide from developers true intentions of the implementation
  • Testing and testable code
    • Main problem with global states (inclugin singletons)
      • They are liars
      • They hide from developers true intentions of the implementation
      • Far from ”clean code that talks”
  • Testing and testable code
    • Dependency Injection
      • Good or bad?
  • Testing and testable code
    • Dependency Injection
      • Library example once again
  • Testing and testable code
    • Dependency Injection
      • Library example once again
      • Common flaw: constructor does real work
        • creating/initializing collaborators
        • communicating with other services
        • logic to set up its own state
  • Testing and testable code
    • Dependency Injection
      • Library example once again
      • Common flaw: constructor does real work
        • creating/initializing collaborators
        • communicating with other services
        • logic to set up its own state
      • Why problem?
        • Inflexible coupled design
        • Unable to inject test mocks
        • It force collaboration on you
          • Object graph
          • Collaboration graph
  • Testing and testable code
    • Dependency Injection
      • Library example
    public class Library { private BookSearch bookSearch; public Library() { this.bookSearch = new BookSearch(); } public boolean addReader(Reader r) { ... } }
  • Testing and testable code
    • Dependency Injection
      • Library example
    public class Library { private BookSearch bookSearch; @Inject public Library(BookSearch bookSearch) { this.bookSearch = bookSearch; } public boolean addReader(Reader r) { ... } }
  • Testing and testable code
    • Using Dependency Injection
      • You end up with loosely coupled design
  • Testing and testable code
    • Using Dependency Injection
      • You end up with loosely coupled design
      • Easy to understand classes
        • Object graph vs creation graph
        • Declarative style of programming
  • Testing and testable code
    • Using Dependency Injection
      • You end up with loosely coupled design
      • Easy to understand classes
        • Object graph vs creation graph
        • Declarative style of programming
      • Tests are easy to write
  • Testing and testable code
    • More? Give us more!
      • I would, simply no time... I think?
      • http://misko.hevery.com/code-reviewers-guide/
  • Testing and testable code
    • Small summery:
  • Testing and testable code
    • Small summery:
      • Just because you write test first, does not mean you are using TDD
  • Testing and testable code
    • Small summery:
      • Just because you write test first, does not mean you are using TDD
      • TDD is about design and requirements
  • Testing and testable code
    • Small summery:
      • Just because you write test first, does not mean you are using TDD
      • TDD is about design and requirements
      • More often you use TDD more addicting it becomes
  • Testing and testable code
    • Small summery:
      • Just because you write test first, does not mean you are using TDD
      • TDD is about design and requirements
      • More often you use TDD more addicting it becomes
      • If used efficiently, you develop your code with good pace, code is readable and maintainable. You rarely hear about regression bugs.
  • Testing and testable code
    • Small summery:
      • Just because you write test first, does not mean you are using TDD
      • TDD is about design and requirements
      • More often you use TDD more addicting it becomes
      • If used efficiently, you develop your code with good pace, code is readable and maintainable. You rarely hear about regression bugs.
      • Bugs Driven Testing – good starting point
  • Testing and testable code
    • Small summery:
      • Just because you write test first, does not mean you are using TDD
      • TDD is about design and requirements
      • More often you use TDD more addicting it becomes
      • If used efficiently, you develop your code with good pace, code is readable and maintainable. You rarely hear about regression bugs.
      • Bugs Driven Testing – good starting point
      • Testable code: clean code that talks
  • Testing and testable code Q&A