test driven development and unit testing l.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Test-Driven Development and Unit Testing PowerPoint Presentation
Download Presentation
Test-Driven Development and Unit Testing

Loading in 2 Seconds...

play fullscreen
1 / 40

Test-Driven Development and Unit Testing - PowerPoint PPT Presentation


  • 182 Views
  • Uploaded on

Test-Driven Development and Unit Testing. Agenda. Writing a Unit Test Asserts Test initialization and destruction Generating Tests. Why unit tests?. To the extent possible, tests should run at all levels unit (smallest granularity) functional (public component contract)

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Test-Driven Development and Unit Testing' - lynton


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
agenda
Agenda
  • Writing a Unit Test
  • Asserts
  • Test initialization and destruction
  • Generating Tests
why unit tests
Why unit tests?
  • To the extent possible, tests should run at all levels
    • unit (smallest granularity)
    • functional (public component contract)
    • integration (components in contact with each other)
  • Time spend testing "in the small" will save time later
    • Agile practitioners write tests first
    • if not first, tests should at least be in small grain, in conjunction with the code being tested
planning unit tests
Planning Unit Tests

public bool AgeCheck (DateTime dayOfBirth)

{

//Method returns true if the person is over age 18, otherwise false

……

}

some tests for agecheck
Some Tests for AgeCheck
  • Check a date from exactly 18 years ago to the day.
  • Check a date from further back in time than 18 years.
  • Check a date from fewer than 18 years ago.
  • Check for a null value.
  • Check for the results based on the very minimum date that can be entered.
  • Check for the results based on the very maximum date that can be entered.
  • Check for an invalid date format being passed to the method.
  • Check two year dates (such as 05/05/03) to determine what century the two-year format is being treated as.
  • Check the time (if that matters) of the date.
unit test areas
Unit Test Areas
  • Boundary Values – min, max, etc.
  • Equality – eg. 18
  • Format – never trust data passed to your application.
  • Culture – 11/26/07 vs. 26/11/07
  • Exception Path
test driven development
Test-Driven Development
  • Write the Unit Test
  • Write enough code for the test to succeed
  • Refactor the code to make it more efficient
why automate tests
Why automate tests?
  • Software without test cases must be assumed defective
  • Manual test cases are unmaintainable
    • no guarantee that all tests will be run regularly, or at all
    • even if tests are run, process is tedious and error-prone
  • Automated testing becomes part of the build process
    • easy to verify that changes do not break existing functionality
    • encourages "build for now"
    • encourages refactoring
test guidelines
Test Guidelines
  • Keep application layered
    • Keep business logic separate from UI
    • Can then test business logic more easily
visual studio team test
Visual Studio Team Test
  • Integrated into Visual Studio
    • Can generate tests from code
    • Setup/Teardown for all tests
    • Setup/teardown for individual tests
    • Methods are annotated to make them a test case
test driven development in visual studio
Test Driven Development in Visual Studio
  • Create a Project
  • Create a related Test Project
    • Write test case
    • Write 'real' code
    • Wash, rinse, repeat
writing a test class

StarshipTest.cs

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespaceDMTest

{

[TestClass]

publicclass StarshipTest

{

[TestMethod]

publicvoid TestWarpFactorLessThanMaxWarp()

{

}

}

}

Writing a Test Class
  • Test class contains test cases
    • Class and test identified by attributes
using asserts

StarshipTest.cs

[TestMethod]

publicvoid TestWarpFactorLessThanMaxWarp()

{

Starship ship = new Starship();

ship.WarpFactor = 5;

Assert.AreEqual<Double>(ship.WarpFactor, 5);

}

Using Asserts
  • Write tests by asserting truths
    • Use Assert class static methods
    • Several methods are available
    • Support different types through generics
assert class
Assert class
  • Static methods
      • AreEqual
      • AreNotEqual
      • AreNotSame
      • AreSame
      • Fail
      • Inconclusive
      • IsFalse
      • IsInstanceOfType
      • IsNotInstanceOfType
      • IsNotNull
      • IsNull
      • IsTrue
collectionassert class
CollectionAssert class
  • Equivalent class for collections
      • AllItemsAreInstancesOfType
      • AllItemsAreNotNull
      • AllItemsAreUnique
      • AreEqual
      • AreEquivalent (same elements)
      • AreNotEqual
      • AreNotEquivalent
      • Contains
      • DoesNotContain
      • IsNotSubsetOf
      • IsSubsetOf
write the code

Starship.cs

namespace Space

{

publicclass Starship

{

privatedouble _warpFactor;

publicdouble WarpFactor

{

get { return _warpFactor; }

set

{

_warpFactor = value;

}

}

}

}

Write the code
  • Write enough code so that the test passes
running tests visual studio
Running tests – Visual Studio
  • Visual Studio Test Manager
    • Controls which tests to run ...
    • ... and when to run them
    • Allows for debugging of tests
managing tests
Managing Tests
  • Test manger
    • Lets you specify the tests to run
    • Add lists of tests
    • Specify tests to run
    • Specify tests to debug
    • Data held in .vsmdi (test metadata) file
configuring test runs
Configuring Test Runs
  • Specify data about test runs
    • Where to run; Enable code coverage; etc…
  • Can have multiple configurations per project
    • Set active configuration in Test menu
testresults directory
TestResults Directory
  • Tests are not run from solution or project directory
    • Special TestResults directory is created
    • Contains subdirectory per test run
    • Subdirectory name is based on the timestamp of current run
    • This contains a directory called 'Out'
    • Tests are run from 'Out' directory
deploymentitem attribute

StarshipTest.cs

[TestMethod]

[DeploymentItem("SomeFile")]

publicvoid TestSomeThing()

{

}

DeploymentItem Attribute
  • Testing code and tested code may need access to files
    • Config files etc
  • Use [DeploymentItem] to copy files to 'out' directory
    • Can specify a single file or a directory
    • Value can be relative or absolute
test results
Test Results
  • Appear in pane
  • Detailed results also available
testing exceptions

StarshipTest.cs

StarshipTest.cs

[TestMethod]

public void TestWarpFactorLessThanMaxWarp(){

try{

Starship ship = new Starship();

ship.WarpFactor = Starship.MAX_WARP / 2;

Assert.AreEqual<Double>(ship.WarpFactor, (Starship.MAX_WARP / 2));

}

catch (Exception){

Assert.Fail("unexpected exception");

}

}

[TestMethod]

[ExpectedException(typeof(ArgumentException))]

public void TestWarpFactorGreaterThanMaxWarp(){

Starship ship = new Starship();

ship.WarpFactor = Starship.MAX_WARP + 2;

}

Testing Exceptions
  • Some code will throw exceptions
    • Can test for expected and unexpected exceptions
write next test

Starship.cs

StarshipTest.cs

[TestMethod]

[ExpectedException(typeof(ArgumentException))]

public void TestWarpFactorGreaterThanMaxWarp()

{

Starship ship = new Starship();

ship.WarpFactor = 11;

}

public double WarpFactor{

get { return _warpFactor; }

set {if (value > MAX_WARP)

thrownew ArgumentException("Invalid warp");

_warpFactor = value;

}

}

Write Next Test
  • Write test
    • write code to ensure test passes
test edge conditions

StarshipTest.cs

StarshipTest.cs

[TestMethod]

[ExpectedException(typeof(ArgumentException))]

public void TestWarpFactorNegative(){

Starship ship = new Starship();

ship.WarpFactor = -1;

}

[TestMethod]

[ExpectedException(typeof(ArgumentException))]

publicvoid TestWarpFactorEqualsMaxWarp(){

Starship ship = new Starship();

ship.WarpFactor = Starship.MAX_WARP;

}

Test Edge Conditions
  • Edge conditions are where things notoriously go wrong
    • negative values
    • values at maximum or minimum
inconclusive tests

StarshipTest.cs

[TestMethod]

public void TestFirePhotonTorpedoe()

{

Starship ship = new Starship();

Assert.Inconclusive("Code not specified");

}

Inconclusive tests
  • Sometimes want a test place holder
    • Can generate an 'inconclusive' assert
    • Used by VSTS when generating test code
ignoring tests

StarshipTest.cs

[TestMethod]

[Ignore]

public void TestFirePhotonTorpedoe()

{

Starship ship = new Starship();

Assert.Inconclusive("Code not specified");

}

Ignoring Tests
  • Used when you do not want the test to run
initializing tests and classes
Initializing Tests and Classes
  • Common code can be refactored
    • Per class initialization
    • Per test initialization
  • Use attributes
      • [ClassInitialize]
      • [ClassCleanup]
      • [TestInitialize]
      • [TestCleanup]
initialization example

StarshipTest.cs

StarshipTest.cs

[TestMethod]

public void TestWarpFactorGreaterEqualsMaxWarp(){

ship.WarpFactor = Starship.MAX_WARP;

}

private Starship ship = null;

[TestInitialize]

public void TestSetup(){

// called for each test

ship = new Starship();

}

Initialization example
  • ClassInitialize used to perform one off initialization
    • Used if per test initialization is too expensive
  • TestInitialization
    • Called per test
    • Better practice than ClassInitialize

Starship created here,

and used here

testing existing code
Testing existing code
  • VSTS can generate tests
    • Not test driven development
    • However, can help with existing code
what does generated code look like

StarshipTest.cs

[TestClass()]

public class StarshipTest

{

[ClassInitialize()]

public void InitializeClass()

{}

[TestInitialize()]

public void SetUp()

{}

[TestMethod()]

public void CurrentWarpFactorTest()

{}

[TestCleanup()]

public void InitializeClass()

{}

[ClassCleanup()]

public void InitializeClass()

{}

}

What does Generated Code Look Like
  • Attributes used to specify class/method behaviour
testing private code

Starship.cs

public class Starship

{

private void TorpedoesLeft(int numberToFire)

{

MaxTorpedoes -= numberToFire;

}

}

Testing Private Code
  • Suppose you have a private method
    • Can’t call this directly from a test case
    • Need to use reflection to call method
    • VSTS will generate a stub to class manage this code
    • Stub has an accessor
calling the private method

StarshipTest.cs

[TestMethod()]

public void TorpedoesLeftTest()

{

Starship target = new Starship();

DMTest.Space_StarshipAccessor accessor =

new DMTest.Space_StarshipAccessor(target);

int numberToFire = 0; // TODO: Initialize to an appropriate value

accessor.TorpedoesLeft(numberToFire);

...

}

Calling the Private Method
  • Test code calls the accessor method
generated code for private test case

Starship.cs

import Microsoft.VisualStudio.TestTools.UnitTesting;

internal class BaseAccessor {

protected PrivateObject m_privateObject;

protected BaseAccessor(object target, PrivateType type) {

m_privateObject = new PrivateObject(target, type);

}

...

}

internal class Space_StarshipAccessor : BaseAccessor {

protected staticPrivateType m_privateType =

new PrivateType(typeof(global::Space.Starship));

internal Space_StarshipAccessor(global::Space.Starship target) :

base(target, m_privateType) {

}

internal void TorpedoesLeft(int numberToFire) {

object[] args = new object[] {numberToFire};

m_privateObject.Invoke("TorpedoesLeft",

new System.Type[] {typeof(int)},

args);

}

}

Generated Code for Private Test Case
  • Access class uses reflection
what is code coverage
What is Code Coverage
  • Information about the code paths executed
    • Can be supplied automatically during unit tests
    • Can instrument code to provide data during other tests
automatic code coverage
Automatic code coverage
  • Create or amend a run configuration
displaying code coverage
Displaying Code Coverage
  • Run tests
    • Display code coverage
code coverage results

code

touched

code not

touched

code partially

touched

Code Coverage Results
  • Code shown in different colours
    • May want to change the colours from the default pastel shades
running test command line

Using MSTest

mstest /testcontainer:StartshipTest\bin\Debug\StartshipTest.dll

mstest /testmetadata:TDD.vsmdi

mstest /runconfig:localtestrun.testrunconfig /testmetadata:tdd.vsmdi

Running test – command line
  • VSTS comes with mstest command line utility
    • useful when using MSBuild to manage build process
summary
Summary
  • VSTS provides a good unit testing framework
    • Can define test class, test cases, etc.
    • Attribute driven
  • Various ways of asserting truth of test
  • Various ways of initializing tests
  • Can generate tests from code
  • Can also test private methods