A Practical Guide To Unit Testing John E. Boal TestDrivenDeveloper.com.

Slides:



Advertisements
Similar presentations
Object Oriented Analysis And Design-IT0207 iiI Semester
Advertisements

Acceptance Testing vs. Unit Testing: A Developers Perspective Owen Rogers Rob Styles
SPL/2010 Test-Driven Development (TDD) 1. SPL/
Test-First Programming. The tests should drive you to write the code, the reason you write code is to get a test to succeed, and you should only write.
CS0004: Introduction to Programming Visual Studio 2010 and Controls.
Test-Driven Development and Refactoring CPSC 315 – Programming Studio.
A Brief Introduction to Test- Driven Development Shawn M. Jones.
E-commerce Project Erik Zeitler Erik Zeitler2 Lab 2  Will be anounced and scheduled later  We will deploy Java Server Pages on a Tomcat server.
Review: Agile Software Testing in Large-Scale Project Talha Majeed COMP 587 Spring 2011.
16/27/2015 3:38 AM6/27/2015 3:38 AM6/27/2015 3:38 AMTesting and Debugging Testing The process of verifying the software performs to the specifications.
Software Testing. “Software and Cathedrals are much the same: First we build them, then we pray!!!” -Sam Redwine, Jr.
Unit testing C# classes “If it isn’t tested it doesn’t work” Unit testing C# classes1.
Chapter 1 Program Design
Xtreme Programming. Software Life Cycle The activities that take place between the time software program is first conceived and the time it is finally.
Algorithm Programming Coding Advices Bar-Ilan University תשס " ו by Moshe Fresko.
Design, Implementation and Maintenance
Test Driven Development Derived from Dr. Fawcett’s notes Phil Pratt-Szeliga Fall 2009.
By Bob Bunson  Simulation of software development project  Fictitious system from Concept to Code  Oriented around the.
By John Boal  Continuous Integration [CI] ◦ Automating the build process ◦ Build the entire system each time any new.
By for Test Driven Development: Industry practice and teaching tool Robert Vanderwall, Ph.D. 1 WISTPC-15.
Test-Driven Development With Visual Studio 2005 Erno de Weerd Info Support.
TDD,BDD and Unit Testing in Ruby
28/08/2015SJF L31 F21SF Software Engineering Foundations ASSUMPTIONS AND TESTING Monica Farrow EM G30 Material available on Vision.
Test Driven Development TDD. Testing ”Testing can never demonstrate the absence of errors in software, only their presence” Edsger W. Dijkstra (but it.
Test Driven Development An approach to writing better code Jimmy Zimmerman Intel Corporation.
Databases with PHP A quick introduction. Y’all know SQL and Databases  You put data in  You get data out  You can do processing on it very easily 
TESTING.
UNIT TESTING FOR SQL Prepared for SUGSA CodeLabs Alain King Paul Johnson.
Sadegh Aliakbary Sharif University of Technology Spring 2012.
© ALEXANDRE CUVA  VERSION 2.00 Test Driven Design.
Test Driven Development Arrange, Act, Assert… Awesome Jason Offutt Software Engineer Central Christian Church
Testing -- Part II. Testing The role of testing is to: w Locate errors that can then be fixed to produce a more reliable product w Design tests that systematically.
Sofia Bulgaria Summer School IST eXPERT: Best Practice on e-Project Development 30 June - 2 July 2003 eXtreme programming.
Software Construction Lecture 18 Software Testing.
A Practical Guide To Unit Testing John E. Boal TestDrivenDeveloper.com.
TEST-1 6. Testing & Refactoring. TEST-2 How we create classes? We think about what a class must do We focus on its implementation We write fields We write.
1 Legacy Code From Feathers, Ch 2 Steve Chenoweth, RHIT Right – Your basic Legacy, from Subaru, starting at $ 20,295, 24 city, 32 highway.
Refactoring & Testability. Testing in OOP programming No life in flexible methodologies and for refactoring- infected developers without SOME kind of.
Chapter 7 The Practices: dX. 2 Outline Iterative Development Iterative Development Planning Planning Organizing the Iterations into Management Phases.
AP-1 4. Agile Processes. AP-2 Agile Processes Focus on creating a working system Different attitude on measuring progress XP Scrum.
Software Engineering 2004 Jyrki Nummenmaa 1 BACKGROUND There is no way to generally test programs exhaustively (that is, going through all execution.
Scalatest. 2 Test-Driven Development (TDD) TDD is a technique in which you write the tests before you write the code you want to test This seems backward,
Software testing techniques Software testing techniques Software Testability Presentation on the seminar Kaunas University of Technology.
Introduction Selenium IDE is a Firefox extension that allows you to record, edit, and debug tests for HTML Easy record and playback Intelligent field selection.
1 Presentation Title Test-driven development (TDD) Overview David Wu.
(1) Test Driven Development Philip Johnson Collaborative Software Development Laboratory Information and Computer Sciences University of Hawaii Honolulu.
HOW A COMPUTER PROCESSES DATA. What is hardware? Hardware is the electric, electronic and mechanical equipment that makes up a computer What is software?
Memory Management OS Fazal Rehman Shamil. swapping Swapping concept comes in terms of process scheduling. Swapping is basically implemented by Medium.
Unit Testing. F-22 Raptor Fighter Manufactured by Lockheed Martin & Boeing How many parts does the F-22 have?
Agenda: Overview of Agile testing Difference between Agile and traditional Methodology Agile Development Methodologies Extreme Programming Test Driven.
Test Driven Development Introduction Issued date: 8/29/2007 Author: Nguyen Phuc Hai.
Unit testing with NUnit Anne Lam & Chris James CMPS 4113 – Software Engineering April 15, 2015.
Automated Testing with PHPUnit. How do you know your code works?
TDD Unit tests from a slightly different point of view Katie Dwyer.
1 © Agitar Software, 2007 Automated Unit Testing with AgitarOne Presented by Eamon McCormick Senior Solutions Consultant, Agitar Software Inc. Presented.
Unit Testing.
Learning to Program D is for Digital.
Test Driven Development 1 November Agenda  What is TDD ?  Steps to start  Refactoring  TDD terminology  Benefits  JUnit  Mocktio  Continuous.
Applied Software Implementation & Testing
Unit testing C# classes
Teaching slides Chapter 9.
(Test Driven) Software Development
History, Characteristics and Frameworks
Lecture 09:Software Testing
Teaching slides Chapter 8.
Test-driven development (TDD)
Computer Science Testing.
CS 240 – Advanced Programming Concepts
Tonga Institute of Higher Education IT 141: Information Systems
Tonga Institute of Higher Education IT 141: Information Systems
Presentation transcript:

A Practical Guide To Unit Testing John E. Boal TestDrivenDeveloper.com

 I am an experienced agile practitioner with many years experience in development and consulting.  I am a certified Scrum Master, and experienced XP practitioner.  I worked for Microsoft, Rockwell, Premera Blue Cross, SolutionsIQ (among others)  I have a BS degree in Computer Science, an electronics engineering and networking background.  I am a Test-Driven Developer  See TestDrivenDeveloper.com  You got a test for that?

 Here is a diagram that illustrates how we can deliver software iteratively using tests to guide our delivery.

 Document the programmer’s intent.  (right, wrong, or otherwise – this is what the programmer wanted the code to do.)  Ensure the code units function as intended.  A suite of UTs gives us a “safety net” when we change code so that we don’t break it by altering it or adding something new.  UTs are a good indicator of how well we understand the code we are writing.

 Level 0 – huh?  What’s a unit test? [Note: U R DOING IT WRONG.]  Level 1 – we write some unit tests.  We wrote some tests that tell us if our code mostly works.  Level 2 – we write (most of) our unit tests first.  We write a unit test then some code, then some more code.  Level 3 – we do Test-Driven Development  We write a unit test, then we write some code to make it pass. Then we refactor, and do it all over again.  Level 4 – we do Acceptance Test-Driven development  We automate our acceptance criteria into acceptance tests first, and then use failing AT’s as a guide to work using UTDD building code and tests until our AT’s pass.

 A small, FAST test that examines a little piece of code (like a single method)  It provides a stimulus to the Code Under Test [CUT] and verifies an expected response.  It is NOT a “scenario,” an end-to-end, or use case verification. These are different kinds of tests and should not be in with true unit tests.  The Unit test and the code it tests should all fit on one screen.

 Reveals the intent of the developer who wrote it  Independent  No side effects, and is isolated from other tests  Has no dependencies on external systems or code  UTs Can be run in any order  Automated (this goes without saying…)  Executes very fast (milliseconds)  Unique – tests something not tested elsewhere  Short and Clear – 5 to 10 lines of code  Coded to same standards as main line code

 Arrange  Setup. Set up all the data and conditions that the test needs to execute. Create anything that is needed for the test to operate independently of its environment.  Mock out any dependent systems  Control all variables not under test  Act  Execution – execute the mainline code  Assert  Validate that the code operated as intended

 SMALL code units.  A unit test ideally should cause execution of no more than 20 lines of main-line code.  (this is only a guideline)  Unit tests are focused on a specific narrow piece of functionality rather than on a broader set.  Method-level, or usually even smaller focus.  We should have many tests for each method.

 We want to ensure that our code works, so we write unit tests to illustrate how the code behaves in specific circumstances.  Test for things that may be null  Test for empty strings…  Test all but the simplest properties. Don’t usually need unit tests for this:  public String Name  {  get  {  return this.name;  }  set  {  this.name = value;  }

 How do we know if we have enough UT’s?  100% code coverage?  Zero bugs?  All Acceptance Tests Passing?  Nope…  We have enough tests when we feel CONFIDENT in our code quality.  If we don’t feel confident that our code works and it’s safe to refactor, keep writing tests…

 Unit tests are code. They need to be maintained.  They cost time to write and they cost more time to maintain.  Beware of writing tests for their own sake.  Trying to hit 100% code coverage is usually not necessary (but it is a usual byproduct of TDD).  Don’t duplicate testing. Test only what hasn’t yet been covered.  Don’t trust UTs that are not well written.  Don’t write complex tests. Keep them simple.

 “Changing existing code to refine its structure without changing its behavior.”  MAKE ONLY SMALL CHANGES AT ONE TIME.  Then test them. With ALL the tests.  Then review them with someone. Then check them in…  This should happen a LOT.  Consider the whole design – not just the classes and methods you happen to be touching.  Think globally, act locally…  Look at the overall design and make refactoring changes accordingly.  Refactor MERCILESSLY.

 Code quality should not be negotiable.  It’s implied that our code should just work.  UT’s and other tests in our test suite help us to know quickly if our code really does what we intended.  UT’s help us know in a few seconds whether a change we make has impact on the code and might affect quality.

 There are always bugs.  If there is a bug, it means someplace we forgot a test! [do we have good acceptance criteria?]  Find a bug, write a test!  DO NOT FIX A BUG WITHOUT A TEST!  Write the test FIRST. This is important.  First the test fails – illustrating the bug. When we fix the bug, the test passes.  We now have a test that ensures the bug will never return. No more regressions!

 Figure out what the code needs to do – exactly [note: this is the HARD part.]  Write a test that illustrates the code does the right thing.  The test fails because there is no code yet.  Write just enough code to make the test pass (this can mean hard-coding the right answer)  Refactor the code keeping all the tests passing, until the overall code and design are good enough to stand up to peer review.  Lather, rinse, repeat.

 Suggested practice is either Acceptance or Unit rather than other test types.  The test describes precisely what the code is to do (behavior).  The test provides specific, controlled input to the code.  The test also controls the environment so the code can operate in a completely pre- determined way.  The test cleans up after itself (no side-effects)

 We now have a failing test. If we don’t – go back.  Write ONLY enough code to pass the test.  This usually means literally hard-code the expected return value.  We do this important step because we need to test the TEST itself.  We saw the test fail, now we want to see it pass. Now we have confidence in the test.

 We had a failing test. Now it’s passing. We now know that the test itself works, so we can now use it as an indicator of real success.  Now is the time when it is SAFE for us to go write real production code!  Write just enough main-line code to do the *real* job at hand while keeping the entire set of tests passing at all times.  This should be like 3 lines of code AT MOST.

 Didn’t we just do this? YES.  We have some working code, some working tests, and everything is functional.  Here we refactor design.  Look at the overall design, examine how things are constructed and work together.  Look for code smells…  Fix them NOW. Don’t wait. Really. This is important! Don’t do anything else until fixed.

 OK, this is getting old… Maybe… but we need to look at the entire system with respect to the changes we’ve introduced with the following critical views:  Performance - Is it fast enough? Did we slow something down with the changes?  Integration - Do we play well with others? Did any interfaces change? If so we probably have lots more work to do…  Security - Do we have a threat model that needs updating? What kinds of security issues might we have introduced?  Acceptance - Last but MOST IMPORTANT… Does it ALL REALLY WORK? Automated Acceptance Tests: run ‘em if you ‘ve got ‘em.

 We are happy with all of our code in the system. Now is the time for review.  Get a code review (it should be really quick because it’s only a small amount of code and a test or two).  Check in the change.  When we know our build is good, we move on to the next small task and go back to Step 1.  Do this a lot. Really. Every hours is good.

 Common Unit Test Patterns  Simple-test – provide input and check result for acceptance or failure.  Code-path – provide values that force the code through a specific path.  Parameter-range – pass a set of parameters that cause success, and a set that cause failure.  Data-driven – pass in sets of data and their expected outcomes  Dependency Injection

 Mock Objects  When programming to interfaces, we get free mock objects, courtesy of frameworks like Rhino Mocks.  Mocks are used to remove dependencies on external systems or components.  Example: Mock Database  If we use an interface to specify how we communicate with storage, we can have a “database” and a “mock” implementation.  The mock will just be programmed to return certain packages of data according to which test is being run.

 “Inversion of Control” pattern (for you pattern buffs)  We can supply our own “version” of a dependency, to suit our own test’s needs.  We’re not testing the dependent component, just how OUR code operates using it… so mock it out.  As long as everyone implements the interface, the main code should not care about what the actual implementation is.  Production code factories construct the “real” ones while test factories construct mocks.  We can eliminate dependencies on external systems, and make our tests FAST too!

 We can use tools like Selenium RC to operate our UI code natively through a browser, under our test’s control.  Tests run under nUnit, MS Test, or anything else we can invent.  Open a page, type in text, click a button.  JavaScript executes, and the test can experience the code just like the user does.  We can write a UI test, and write the code to make it pass just like any other unit test.

 Tests run in an actual browser, when it takes time to process things in that browser, the test must wait for it…  Pre-Set wait times cause problems when the system is running slower than we expected  Selenium has WaitForEvent() that we can use (ideally) to wait just long enough for something to happen.  Pop-up windows are a pain to work with…

 We all write a lot of JavaScript code now for our pages. Web 2.0 and Ajax require lots of stuff to happen on the client now.  We should be unit-testing the JavaScript code, just like all the other code we write.  JSUnit is one tool that can make unit testing JavaScript much easier.  Don’t mix your JavaScript logic with UI manipulation, separate the functionality. Test logic with JSUnit, and UI code with Selenium.

 Database code needs tests also!  We can write SQL unit tests in SQL  I prefer to write nUnit tests for SQL code, and drive it from the unit test framework.  Either way works…  Independence – design tests so that one test does not affect others  We can still use TDD to write the test first … the paradigm still holds.

 The big trick is putting the database into a “known state” for each test, then undoing the changes at the end of the test…  The test can wrap everything in a transaction using a try block, then roll it back in the finally() block  Test Tables.  Test Views.  Test Stored Procedures and Functions.

 Create a way to get the metadata  “describe()” is one way to do it.  Have the UT framework setUp() create the describe procedure, and the tearDown() remove it (zero residual side effects)  Write tests that verify the column count, order, type, length, and nullability  These guarantee we have the right structure.

CREATE PROCEDURE describe VARCHAR(90)) AS SELECT DISTINCT sc.column_id AS ColumnNumber, cols.column_name AS Name, cols.data_type AS Type, ISNULL(cols.character_maximum_length, 0) AS Length, cols.is_nullable AS Nullable FROM information_schema.columns cols INNER JOIN sys.columns sc ON cols.column_name = sc.name AND OBJECT_NAME(sc.object_id) ORDER BY sc.column_id

 NUnit – the standard.  TestDriven.Net – VS- integrated test runner  Selenium RC – the best in UI testing  Selenium IDE:   Rhino Mocks – mock object framework  JSUnit – JavaScript Unit Testing  reSharper - if you use C# and Visual Studio

 Agile Testing  Lisa Crispin  xUnit Test Patterns – Refactoring Test Code  Gerard Mezaros  Refactoring to Patterns  Joshua Kerievsky  Refactoring – Improving the Design of Existing Code  Martin Fowler  TestDrivenDeveloper.com

 Test it well  Test it ONCE  Refactor a lot

 Any questions?  Thanks for listening!