bad test, good test

34
Bad Test, Good Test Seb Rose Claysnow Limited @sebrose

Upload: seb-rose

Post on 06-May-2015

3.040 views

Category:

Technology


1 download

DESCRIPTION

Slides from my presentation at DunDDD, 17th Nov 2012. Most of this session was spent discussing unit test examples harvested from github. If anyone would like to see them, just ask.

TRANSCRIPT

Page 1: Bad test, good test

Bad Test, Good Test

Seb RoseClaysnow Limited

@sebrose

Page 2: Bad test, good test

Take an index card

What makes a unit test good or bad?

- Write 3 ‘good’ things on one side

- Write 3 ‘bad’ things on the other side

Page 3: Bad test, good test

What is a unit test?

Page 4: Bad test, good test

Understandable

Page 5: Bad test, good test

@Test public void scale() { Date now = new Date();

Calendar calBegin = Calendar.getInstance(); calBegin.setTime(now); calBegin.add(Calendar.HOUR, -4); Date begin = calBegin.getTime();

Period p = new Period(4); long delta = p.getBegin().getTime() -

begin.getTime(); Assert.assertTrue(

p.getEnd().compareTo(now) >= 0); logger.trace(delta); Assert.assertTrue(delta < 10 && delta > -10); Assert.assertEquals(

new Integer(4), new Integer(p.getScale())); }

Page 6: Bad test, good test

[Test] public void asterisk_should_format_to_em() {

// ContextFormatter f = new MarkdownFormatter();String expected = "This is <em>em</em> text";

// ActionString actual = f.Format("This is *em* text");

// OutcomeAssert.AreEqual(expected, actual);

}

Page 7: Bad test, good test

Maintainable

Page 8: Bad test, good test

@Test public void smoker_requires_manual_referral() {

Customer customer = new Customer(“Joe”, “Smith”,“12/12/1980”, “Accountant”, “$300,000”, “Yes”, “No”);

Referral referral = underwriting.process(customer);

Assert.assertEquals(Referral.Manual, referral); }

Page 9: Bad test, good test

@Test public void non_smoker_does_not_require_referral() {

Customer customer = new Customer(“Joe”, “Smith”,“12/12/1980”, “Accountant”, “$300,000”, “No”, “No”);

Referral referral = underwriting.process(customer);

Assert.assertEquals(Referral.None, referral); }

Page 10: Bad test, good test

public interface CustomerBuilder {public CustomerBuilder standardSingleMale();public CustomerBuilder standardSingleFemale();

public CustomerBuilder smoker();public CustomerBuilder hasOccupation(String occupation);

public Customer build();}

Page 11: Bad test, good test

@Test public void non_smoker_does_not_require_referral() {

Customer customer = customerBuilder.standardSingleMale().build();

Referral referral = underwriting.process(customer);

Assert.assertEquals(Referral.None, referral); }

Page 12: Bad test, good test

@Test public void smoker_requires_manual_referral() {

Customer customer = customerBuilder.standardSingleFemale().smoker().build();

Referral referral = underwriting.process(customer);

Assert.assertEquals(Referral.Manual, referral); }

Page 13: Bad test, good test

Repeatable

Page 14: Bad test, good test

@Test public void testRolling() { Yahtzee y = Yahtzee.roll(); assertEquals(y, y); Yahtzee y1 = new Yahtzee(1,2,3,4,5); Yahtzee y2 = new Yahtzee(1,2,3,4,5); assertTrue(y1.equals(y2)); assertEquals(y1,y2); assertFalse(Yahtzee.roll()==Yahtzee.roll()); }

Page 15: Bad test, good test

Necessary

Page 16: Bad test, good test

[Test]#region TestCase...public void TestMapFromRomanNormalToRomanOnes(

string roman, int times) {

var actual = _engine.ToRomanOnes(roman);var expected = _engine.Repeat('I', times);

Assert.That(actual, Is.EqualTo(expected));}

Page 17: Bad test, good test

Granular

Page 18: Bad test, good test

@Test public void testRolling() { Yahtzee y = Yahtzee.roll(); assertEquals(y, y); Yahtzee y1 = new Yahtzee(1,2,3,4,5); Yahtzee y2 = new Yahtzee(1,2,3,4,5); assertTrue(y1.equals(y2)); assertEquals(y1,y2); assertFalse(Yahtzee.roll()==Yahtzee.roll()); }

Page 19: Bad test, good test

Fast

Page 20: Bad test, good test

Properties of unit testing

UnderstandableMaintainableRepeatableNecessaryGranular

Fast

Page 21: Bad test, good test

Look back at your index card

For each of your ‘good’ things, which of the properties does it exhibit?

For each of your ‘bad’ things, which of the properties does it contravene?

Page 22: Bad test, good test

Have I missed any?

Page 23: Bad test, good test

None of this is a substitutefor writing testable code.

Page 24: Bad test, good test

class PriceCalculator {public Price getPrice() {

if (DateTime.Compare(DateTime.Now,PRICE_RISE_DATE)<0){return LOW_PRICE;

} else {return HIGH_PRICE;

}}

}

Page 25: Bad test, good test

[Test] public void prices_should_increase_on_2013_03_31() {

PriceCalculator calc = new PriceCalculator();

// How can we set the date?// ...

}

Page 26: Bad test, good test

class PriceCalculator {public PriceCalculator( SystemClock clock ) {

clock_ = clock;}

public Price getPrice() {if (DateTime.Compare(clock.Now, PRICE_RISE_DATE)<0){

return LOW_PRICE;} else {

return HIGH_PRICE;}

}}

Page 27: Bad test, good test

[Test] public void prices_should_increase_on_2013_03_31() {

SystemClock clock = new SystemClock(2013, 03, 31);PriceCalculator calc = new PriceCalculator(clock);

// Now we control the date?// ....

}

Page 28: Bad test, good test
Page 29: Bad test, good test

How can we improve?

Page 30: Bad test, good test
Page 31: Bad test, good test

Properties of unit testing

UnderstandableMaintainableRepeatableNecessaryGranular

Fast

Page 32: Bad test, good test

Unit tests are your executable specification

Treat them with as much respect as your production code

Page 33: Bad test, good test

The Feather’s definition of legacy code:

Code that has no tests

Page 34: Bad test, good test

Seb Rose

Twitter: @sebroseBlog: www.claysnow.co.ukE-mail: [email protected]