Test driven development

30
Test-Driven Development (TDD) Sharafat Ibn Mollah Mosharraf Software Engineer, Therap (BD) Ltd. [email protected]

description

This presentation is simply for motivating developers towards test automation and test-driven development. It discusses lightly unit testing, mocking and integration testing, too.

Transcript of Test driven development

Page 1: Test driven development

Test-Driven Development(TDD)

Sharafat Ibn Mollah Mosharraf

Software Engineer,Therap (BD) Ltd.

[email protected]

Page 2: Test driven development

Overview

● The need for test automation● Writing test-first code

● Unit Test Frameworks● Mocking Frameworks

● Integration Testing● Continuous Integration Tools

Test-Driven Development (TDD) 2 / 29

Page 3: Test driven development

The Need for Test Automation

Test-Driven Development (TDD) 3 / 29

Page 4: Test driven development

Traditional Programming Practice - 1● We code, build, deploy to app server and manually test

whether our code works.● We repeat the same process until we're affirmed that our

code works.● If code building takes 1 minute, server restarting takes 2 minutes, logging in and browsing to the desired page to test the code takes 1 minute, then one round of testing takes a total of 4 minutes.● If 10 rounds are needed to finally make the code work, total

time wasted is 40 minutes.● If testing could be automated by bypassing these lengthy

processes, then this 40 minutes could be saved.Test-Driven Development (TDD) 4 / 29

Page 5: Test driven development

Traditional Programming Practice - 2List of all users of an application

uses returns ACTIVE, LOCKED, DISABLED users

1

List of LOCKED users to reset their password2 uses but gets ALL users returned

instead of only LOCKED users

3 Naive coder changes to return only LOCKED users.

(2) works awesome, but now (1) doesn't work as expected.However, the naive coder didn't even know feature (1) exists, so, the new bug in (1) gets overlooked until customer complaints.

consequence

Don't trust coders!! Whenever a new feature is implemented, test the whole system again.

R u crazy?? There are hundreds of features in the app!!!

lesson learned

Automate the testing process :)solution

Page 6: Test driven development

Okay, understood. After writing code, we need to write test codes, too.

WRONG!!!We need to write test code before writing actual code.

Why on earth is that???

Test-Driven Development (TDD) 6 / 29

Page 7: Test driven development

Writing Test Code After Writing Actual Code is Difficult

Before we learn why, let's take a look at how a test code can be written

Test-Driven Development (TDD) 7 / 29

Page 8: Test driven development

Writing Naive Test Code

Actual code: Test code:

Test-Driven Development (TDD) 8 / 29

Page 9: Test driven development

Writing Test Code After Actual Code Becomes Difficult - An Example

Actual (pseudo)code: The test code should do something like the following:

1. Add a few users including ACTIVE, LOCKED & DISABLED to database.2. Call the actual code where the user list is retrieved.3. Check whether all the users added above have been returned.

But we can't single-out the actual code where user list is retrieved; that task is buried under the listUsers() method which returns nothing!

Test-Driven Development (TDD) 9 / 29

Page 10: Test driven development

Writing Testable Code1. Write the test code first:

Test-Driven Development (TDD) 10 / 29

Page 11: Test driven development

Writing Testable Code...2. Make sure your test code fails when run.

Huh! I haven't implemented the code yet! The test code will obviously fail!!

Wrong again!! :P

Quite interestingly, your test code might pass before you've written your actual code, which indicates your test code itself is incorrectly

written and needs to be tested... :P

Test-Driven Development (TDD) 11 / 29

Page 12: Test driven development

Writing Testable Code...3. Now write the actual code in the way expected by the test code:

4. Run the test.If the test passes, move on to the next step (step 5).If the test fails, find out the bug in your actual code and fix it. Run the test

again until it passes.5. Write some more test code if you have other codes which can be tested. Repeat steps 1 to 4 for those code.6. Finish off the rest of the code: (see next slide)

Test-Driven Development (TDD) 12 / 29

Page 13: Test driven development

Writing Testable Code...

Code Coverage (33.33%)

Test-Driven Development (TDD) 13 / 29

Page 14: Test driven development

Added Bonus of TDD

● Code conforms to good software design principles:

■ Low coupling■ High cohesion

● Test code becomes the documentation and usage example of the written application/API

■ However, you need to make sure you write the test code well, following good practices, standards and patterns.

Test-Driven Development (TDD) 14 / 29

Page 15: Test driven development

Unit Testing Frameworks

● The previous -based test code is not very appealing as the test program fails

■ at the first assertion failure line, skipping the evaluation of the rest of the assertions

■ with simply an "assertion failed" message without any clue about what the actual value of something was

● We want to■ check all assertions and figure out which specific

ones fails■ compare the actual value to the expected one

Test-Driven Development (TDD) 15 / 29

Page 16: Test driven development

Unit Testing Frameworks...

● Several frameworks have been developed for the aforementioned purposes:

■ xUnit (JUnit, PHPUnit, NUnit, DBUnit etc.)■ TestNG

● And a lot more...

● The above test code written in JUnit would look like the following:

Test-Driven Development (TDD) 16 / 29

Page 17: Test driven development

Unit Testing Frameworks...

Test-Driven Development (TDD) 17 / 29

Page 18: Test driven development

Mocking

● Unit testing is for testing an independent unit of code.

● Unit testing assumes the code to be tested is independent of any other code.

● However, in the previous example, the code to be tested ( ) is dependent on database.

● To remove the dependency, the actual object (database in our example) is replaced with a fake object, known as a mock object.

Test-Driven Development (TDD) 18 / 29

Page 19: Test driven development

Naive Approach for Mocking

Actual Code:

Test-Driven Development (TDD) 19 / 29

Page 20: Test driven development

Naive Approach for Mocking...

Mock Connection Implementation:

Test-Driven Development (TDD) 20 / 29

Page 21: Test driven development

Naive Approach for Mocking...

Test Code:

Test-Driven Development (TDD) 21 / 29

Page 22: Test driven development

Mocking Frameworks

● To ease the tedious task of creating mock objects, several mocking frameworks have been developed, the most populars among which are (Java-only mentioned here):

■ EasyMock, PowerMock■ Mockito

● Using Mockito would save you from writing the MockConnection class above and make the aforementioned test code look like the following: (see next slide)

Test-Driven Development (TDD) 22 / 29

Page 23: Test driven development

Mocking Frameworks...

Test Code:

Test-Driven Development (TDD) 23 / 29

Page 24: Test driven development

Unit Testing is Not Enough for Test Automation

● If the previous test for passes, does that guarantee your application works?No.

● The independence nature of code unit is the culprit.

● The previous test passes with a mock connection. But when real database will be used, there is a chance of things not going well altogether.(Can you come up with a few ideas why?)

Test-Driven Development (TDD) 24 / 29

Page 25: Test driven development

Unit vs Integration Testing - Analogy● When small units are tested independent of one another, it's called

unit testing.● When the interaction among components are tested, it's called

integration testing.● Suppose you're building a car and you've unit tested and confirmed

that your tires work as expected, engine works as expected, speedometer works as expected - all parts independent of one another.Now, when you build a car whose wheels are 215/65/15*, but you fit 205/55/15 tires to it, if you run an integration test, you'll find out that driving the car at 55 MPH causes the speedometer to read 60 MPH (as the actual tire circumference is 8.2% shorter than the expected one), which is an error.Integration tests are used to identify such error.

* 215/65/15 is nominal width of tire (in mm) / ratio of height to width (aspect ratio) / rim diameter code

Test-Driven Development (TDD) 25 / 29

Page 26: Test driven development

Continuous Integration Tools● There is no syntactic difference between unit and integration

testing; the difference is rather semantic.● As the environment setup for integration test is complex and

running the tests take much time, integration testing is usually performed in a dedicated server.

● Developers commit their code to the server and before the commits get merged, all the integration tests are run to make sure the commits don't cause other parts of the application to break.

● Developers get notified by the CI server automatically of the result of the tests.

● Some most popular CI tools include (only Java-specifics are mentioned here):

■ CruiseControl■ Hudson

Test-Driven Development (TDD) 26 / 29

Page 27: Test driven development

Principles of Continuous Integration

● Maintain a Code Repository● Automate the build● Make the build self-testing● Everyone commits to the baseline● Every commit (to baseline) should be built● Keep the build fast● Test in a clone of production environment● Make it easy to get the latest deliverables● Everyone can see the results of the latest

builds● Automate deployment

Test-Driven Development (TDD) 27 / 29

Page 28: Test driven development

Further ReadingTest Driven Development: By ExampleKent BeckAddison-Wesley (2002)

xUnit Test Patterns: Refactoring Test CodeGerard MeszarosAddison-Wesley (2007)

Clean Code: A Handbook of Agile Software CraftsmanshipRobert C. MartinPrentice Hall (2008)

Test-Driven Development (TDD) 28 / 29

Page 30: Test driven development