Transcript
Page 1: Testing the Next Generation

T E S T I N G T H E N E X T G E N E R AT I O N

M I K E H A R R I S

Page 2: Testing the Next Generation
Page 3: Testing the Next Generation

fscheck

specflow

Page 4: Testing the Next Generation

is testing oftraits

specflow

Page 5: Testing the Next Generation

is testing ofproperties

fscheck

Page 6: Testing the Next Generation
Page 7: Testing the Next Generation

B E I N G

Page 8: Testing the Next Generation
Page 9: Testing the Next Generation
Page 10: Testing the Next Generation
Page 11: Testing the Next Generation
Page 12: Testing the Next Generation

B E I N G

Page 13: Testing the Next Generation

B E I N G T H I N G S

Page 14: Testing the Next Generation

B E I N G T H I N G S

A S M A R T I N H E I D E G G E R S P E A K S O F T H E M I N

“ T H E O R I G I N O F T H E W O R K O F A R T "

Page 15: Testing the Next Generation

I N T E R P R E TAT I O N S O F T H I N G S

• substances with properties or as bearers of traits

• sense perceptions

• formed stuff

Page 16: Testing the Next Generation

S U B S TA N C E S W I T H P R O P E R T I E S O R A S B E A R E R S O F T R A I T S

Page 17: Testing the Next Generation
Page 18: Testing the Next Generation

fscheck

specflow

Page 19: Testing the Next Generation

is testing oftraits

specflow

Page 20: Testing the Next Generation

is testing ofproperties

fscheck

Page 21: Testing the Next Generation

S U B S TA N C E S W I T H P R O P E R T I E S O R A S B E A R E R S O F T R A I T S

Page 22: Testing the Next Generation
Page 23: Testing the Next Generation

Testing of Traits

Page 24: Testing the Next Generation

is testing oftraits

specflow

Page 25: Testing the Next Generation
Page 26: Testing the Next Generation

I N E E D A F I Z Z B U Z Z T R A N S L AT O R

Page 27: Testing the Next Generation

C H E C K P O I N T 1 ) N O B M I ' D I V I S I B L E P O N G 3 F I Z Z J I C H E G H ' O H . N O B M I ' D I V I S I B L E P O N G 5 B U Z Z J I C H E G H ' O H . L AT L H S O ' M E H J I C H E G H ‘ O H . !2 )⎕ I O← 0 ( L , ' F I Z Z ' ' B U Z Z ' ' F I Z Z B U Z Z ' ) [ ¯ 1 +( L×W = 0 ) + W← ( 1 0 0×~ 0 = W ) + W←⊃ + / 1 2× 0 = 3 5 |

⊂ L← 1 +⍳ 1 0 0 ]

Page 28: Testing the Next Generation

S A M E PA G E !

Page 29: Testing the Next Generation

C H E C K P O I N T 2 - > 2 3 - > F I Z Z 4 - > 4 5 - > B U Z Z 6 - > F I Z Z

Page 30: Testing the Next Generation

M A K E I T S O .

Page 31: Testing the Next Generation
Page 32: Testing the Next Generation

F I Z Z B U Z Z

Page 33: Testing the Next Generation

FizzBuzz(1 ) => “1” FizzBuzz(2 ) => “2” FizzBuzz(3 ) => “Fizz” FizzBuzz(4 ) => “4” FizzBuzz(5 ) => “Buzz” FizzBuzz(6 ) => “Fizz” … FizzBuzz(15) => “FizzBuzz”

Page 34: Testing the Next Generation

namespace FizzBuzz { public class FizzBuzzer { public string Translate(int value) { var result = string.Empty; if (value % 3 == 0) result += "Fizz"; if (value % 5 == 0) result += "Buzz"; return string.IsNullOrEmpty(result) ? value.ToString() : result; } } }

Page 35: Testing the Next Generation

T E S T I N G T R A I T S

Page 36: Testing the Next Generation

T H E N U N I T W AY

Page 37: Testing the Next Generation

[TestCase( 2, Result = "2")] [TestCase( 3, Result = "Fizz")] [TestCase( 4, Result = "4")] [TestCase( 5, Result = "Buzz")] [TestCase( 6, Result = "Fizz")] [TestCase(10, Result = "Buzz")] [TestCase(15, Result = "FizzBuzz")] [TestCase(45, Result = "FizzBuzz")] public string FizzBuzz_Tests(int value) { return fizzbuzzer.Translate(value); }

Page 38: Testing the Next Generation

S P E C F L O W W AY

Page 39: Testing the Next Generation

Feature: FizzBuzzerSpec In order to be able to communicate with the FizzBuzzons As a Starfleet Captain I want to be able to translate numbers to their FizzBuzz value

Page 40: Testing the Next Generation

Scenario: 2 must translate to the string 2 Given a FizzBuzzer And the value of '2' When translate is invoked Then the result should be '2'

Page 41: Testing the Next Generation

Scenario: 3 must translate to the string Fizz Given a FizzBuzzer And the value of '3' When translate is invoked Then the result should be 'Fizz'

Page 42: Testing the Next Generation

Scenario: 5 must translate to the string Buzz Given a FizzBuzzer And the value of '5' When translate is invoked Then the result should be 'Buzz'

Page 43: Testing the Next Generation

Scenario: 15 must translate to the string FizzBuzz Given a FizzBuzzer And the value of '15' When translate is invoked Then the result should be 'FizzBuzz'

Page 44: Testing the Next Generation

Feature: FizzBuzzerSpec In order to be able to communicate with the FizzBuzzons As a Starfleet Captain I want to be able to translate numbers to their FizzBuzz value Scenario: 2 must translate to the string 2 Given a FizzBuzzer And the value of '2' When translate is invoked Then the result should be '2' Scenario: 3 must translate to the string Fizz Given a FizzBuzzer And the value of '3' When translate is invoked Then the result should be 'Fizz' Scenario: 5 must translate to the string Buzz Given a FizzBuzzer And the value of '5' When translate is invoked Then the result should be 'Buzz' Scenario: 15 must translate to the string FizzBuzz Given a FizzBuzzer And the value of '15' When translate is invoked Then the result should be 'FizzBuzz'

Page 45: Testing the Next Generation
Page 46: Testing the Next Generation

Feature: FizzBuzzerSpec In order to be able to communicate with the FizzBuzzons As a Starfleet Captain I want to be able to translate numbers to their FizzBuzz value

Page 47: Testing the Next Generation

Scenario: 2 must translate to the string 2 Given a FizzBuzzer And the value of '2' When translate is invoked Then the result should be '2'

Page 48: Testing the Next Generation

using FizzBuzz; using TechTalk.SpecFlow; using NUnit.Framework; namespace FizzBuzzSpec { [Binding] public class FizzBuzzerSpecSteps { [Given(@"a FizzBuzzer")] public void GivenAFizzBuzzer() { ScenarioContext.Current.Add("FizzBuzzer", new FizzBuzzer()); } [Given(@"the value of '(.*)'")] public void GivenTheValueOf(int value) { ScenarioContext.Current.Add("value", value); } [When(@"translate is invoked")] public void WhenTranslateIsInvoked() { var fizzbuzzer = ScenarioContext.Current.Get<FizzBuzzer>("FizzBuzzer"); var value = ScenarioContext.Current.Get<int>("value"); ScenarioContext.Current.Add("actual", fizzbuzzer.Translate(value)); } [Then(@"the result should be '(.*)'")] public void ThenTheResultShouldBe(string expected) { var actual = ScenarioContext.Current.Get<string>("actual"); Assert.That(expected, Is.EqualTo(actual)); } } }

Page 49: Testing the Next Generation

Given a FizzBuzzer !

[Given(@"a FizzBuzzer")] public void GivenAFizzBuzzer() { ScenarioContext.Current.Add( "FizzBuzzer", new FizzBuzzer()); }

Page 50: Testing the Next Generation

And the value of '2' !

[Given(@"the value of '(.*)'")] public void GivenTheValueOf(int value) { ScenarioContext.Current.Add("value", value); }

Page 51: Testing the Next Generation

When translate is invoked [When(@"translate is invoked")] public void WhenTranslateIsInvoked() { var fizzbuzzer = ScenarioContext .Current.Get<FizzBuzzer>("FizzBuzzer"); var value = ScenarioContext .Current.Get<int>("value"); ScenarioContext .Current.Add( "actual", fizzbuzzer.Translate(value)); }

Page 52: Testing the Next Generation

Then the result should be '2' [Then(@"the result should be '(.*)'")] public void ThenTheResultShouldBe( string expected) { var actual = ScenarioContext .Current.Get<string>("actual"); Assert.That(expected, Is.EqualTo(actual)); }

Page 53: Testing the Next Generation

Scenario: 2 must translate to the string 2 Given a FizzBuzzer And the value of '2' When translate is invoked Then the result should be '2'

Page 54: Testing the Next Generation

Scenario: 5 must translate to the string Buzz Given a FizzBuzzer And the value of '5' When translate is invoked Then the result should be 'Buzz'

Page 55: Testing the Next Generation

Given a FizzBuzzer !

[Given(@"a FizzBuzzer")] public void GivenAFizzBuzzer() { ScenarioContext.Current.Add( "FizzBuzzer", new FizzBuzzer()); }

Page 56: Testing the Next Generation

And the value of '5' !

[Given(@"the value of '(.*)'")] public void GivenTheValueOf(int value) { ScenarioContext.Current.Add("value", value); }

Page 57: Testing the Next Generation

When translate is invoked [When(@"translate is invoked")] public void WhenTranslateIsInvoked() { var fizzbuzzer = ScenarioContext .Current.Get<FizzBuzzer>("FizzBuzzer"); var value = ScenarioContext .Current.Get<int>("value"); ScenarioContext .Current.Add( "actual", fizzbuzzer.Translate(value)); }

Page 58: Testing the Next Generation

Then the result should be 'Buzz' [Then(@"the result should be '(.*)'")] public void ThenTheResultShouldBe( string expected) { var actual = ScenarioContext .Current.Get<string>("actual"); Assert.That(expected, Is.EqualTo(actual)); }

Page 59: Testing the Next Generation
Page 60: Testing the Next Generation
Page 61: Testing the Next Generation
Page 62: Testing the Next Generation

Scenario: 2 must translate to the string 2 Given a FizzBuzzer And the value of '2' When translate is invoked Then the result should be '2'

Page 63: Testing the Next Generation

[NUnit.Framework.TestAttribute()] [NUnit.Framework.DescriptionAttribute("2 must translate to the string 2")] public virtual void _2MustTranslateToTheString2() { TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo( "2 must translate to the string 2", ((string[])(null))); #line 6 this.ScenarioSetup(scenarioInfo); #line 7 testRunner.Given("a FizzBuzzer", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line 8 testRunner.And("the value of \'2\'", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 9 testRunner.When("translate is invoked", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 10 testRunner.Then("the result should be \'2\'", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden this.ScenarioCleanup(); }

Page 64: Testing the Next Generation

G O O D , B U T N O T G R E AT.

Page 65: Testing the Next Generation
Page 66: Testing the Next Generation

Examples: | value | expected value | | 2 | 2 | | 4 | 4 | | 3 | Fizz | | 9 | Fizz | | 5 | Buzz | | 25 | Buzz | | 15 | FizzBuzz | | 30 | FizzBuzz |

Page 67: Testing the Next Generation

Scenario Outline: FizzBuzz translation Given a FizzBuzzer And the value of '<value>' When translate is invoked Then the result should be '<expected value>' Examples: | value | expected value | | 2 | 2 | | 4 | 4 | | 3 | Fizz | | 9 | Fizz | | 5 | Buzz | | 25 | Buzz | | 15 | FizzBuzz | | 30 | FizzBuzz |

Page 68: Testing the Next Generation

[Given(@"a FizzBuzzer")] public void GivenAFizzBuzzer() { ScenarioContext.Current.Add( "FizzBuzzer", new FizzBuzzer()); }

Page 69: Testing the Next Generation

[Given(@"the value of '(.*)'")] public void GivenTheValueOf(int value) { ScenarioContext.Current.Add("value", value); }

Page 70: Testing the Next Generation

[When(@"translate is invoked")] public void WhenTranslateIsInvoked() { var fizzbuzzer = ScenarioContext .Current.Get<FizzBuzzer>("FizzBuzzer"); var value = ScenarioContext .Current.Get<int>("value"); ScenarioContext .Current.Add( "actual", fizzbuzzer.Translate(value)); }

Page 71: Testing the Next Generation

[Then(@"the result should be '(.*)'")] public void ThenTheResultShouldBe( string expected) { var actual = ScenarioContext .Current.Get<string>("actual"); Assert.That(expected, Is.EqualTo(actual)); }

Page 72: Testing the Next Generation

Examples: | value | expected value | | 2 | 2 | | 4 | 4 | | 3 | Fizz | | 9 | Fizz | | 5 | Buzz | | 25 | Buzz | | 15 | FizzBuzz | | 30 | FizzBuzz |

Page 73: Testing the Next Generation

[TestCase( 2, Result = "2")] [TestCase( 3, Result = "Fizz")] [TestCase( 4, Result = "4")] [TestCase( 5, Result = "Buzz")] [TestCase( 6, Result = "Fizz")] [TestCase(10, Result = "Buzz")] [TestCase(15, Result = "FizzBuzz")] [TestCase(45, Result = "FizzBuzz")] public string FizzBuzz_Tests(int value) { return fizzbuzzer.Translate(value); }

Page 74: Testing the Next Generation

Examples: | value | expected value | | 2 | 2 | | 4 | 4 | | 3 | Fizz | | 9 | Fizz | | 5 | Buzz | | 25 | Buzz | | 15 | FizzBuzz | | 30 | FizzBuzz |

Page 75: Testing the Next Generation

G R E AT.

Page 76: Testing the Next Generation
Page 77: Testing the Next Generation
Page 78: Testing the Next Generation
Page 79: Testing the Next Generation
Page 80: Testing the Next Generation
Page 81: Testing the Next Generation
Page 82: Testing the Next Generation

"FizzBuzzSpec\FizzBuzzSpec\FizzBuzzerSpecFeature\_15MustTranslateToTheStringFizzBuzz","Passed","00:00:00.183","(local)" Given a FizzBuzzer -> done: FizzBuzzerSpecSteps.GivenAFizzBuzzer() (0.0s) And the value of '15' -> done: FizzBuzzerSpecSteps.GivenTheValueOf(15) (0.0s) When translate is invoked -> done: FizzBuzzerSpecSteps.WhenTranslateIsInvoked() (0.0s) Then the result should be 'FizzBuzz' -> done: FizzBuzzerSpecSteps.ThenTheResultShouldBe("FizzBuzz") (0.0s)

Page 83: Testing the Next Generation
Page 84: Testing the Next Generation
Page 85: Testing the Next Generation
Page 86: Testing the Next Generation
Page 87: Testing the Next Generation
Page 88: Testing the Next Generation

D O E S T H I S R E A L LY W O R K ? ! ?

Page 89: Testing the Next Generation

W E C O U L D H AV E T H E S Y S T E M G E N E R AT E D ATA F O R U S

T O I L L U S T R AT E T H E A D H E R E N C E O F P R O P E R T I E S

Page 90: Testing the Next Generation

M A K E I T S O .

Page 91: Testing the Next Generation
Page 92: Testing the Next Generation

Testing of Properties

Page 93: Testing the Next Generation

is testing ofproperties

fscheck

Page 94: Testing the Next Generation

T E S T I N G P R O P E R T I E S

Page 95: Testing the Next Generation

T H E N U N I T W AY

Page 96: Testing the Next Generation

[Test] public void Divisible_By_3_Is_Fizz( [Range(3, 300, 3)] int value) { var removeBuzz = (value % 5 == 0) ? 3 : value; Assert.That(FizzBuzz(removeBuzz), Is.EqualTo("Fizz")); }

Page 97: Testing the Next Generation

[Test] public void Divisible_By_5_Is_Buzz( [Random(1, 10000, 100)] int value) { var removeFizz = (value % 3 == 0) ? 5 : value * 5; Assert.That(FizzBuzz(removeFizz), Is.EqualTo("Buzz")); }

Page 98: Testing the Next Generation

F S C H E C K W AY

Page 99: Testing the Next Generation

[TestCase] public void Number_Divisible_By_3_Will_Return_Fizz() { Spec.ForAny<int>(value => _fizzBuzzer.Translate(value).Equals("Fizz")) .When(value => value % 3 == 0 && value % 5 != 0) .QuickCheckThrowOnFailure(); }

Page 100: Testing the Next Generation

Ok, passed 100 tests.

Page 101: Testing the Next Generation

[TestCase] public void Number_Divisible_By_5_Will_Return_Buzz() { Spec.ForAny<int>(value => _fizzBuzzer.Translate(value).Equals("Buzz")) .When(value => value % 3 != 0 && value % 5 == 0) .QuickCheckThrowOnFailure(); }

Page 102: Testing the Next Generation

Ok, passed 100 tests.

Page 103: Testing the Next Generation

[TestCase] public void Number_Divisible_By_15_Returns_FizzBuzz() { Spec.ForAny<int>(value => _fizzBuzzer.Translate(value).Equals("FizzBuzz")) .Or(value => value % 15 != 0) .QuickCheckThrowOnFailure(); }

Page 104: Testing the Next Generation

Ok, passed 100 tests.

Page 105: Testing the Next Generation

H M M M M

Page 106: Testing the Next Generation

W E C O U L D C R E AT E A M O D E L T O D E M O N S T R AT E T H E

R O B U S T N E S S O F T H E S O L U T I O N

Page 107: Testing the Next Generation

M A K E I T S O .

Page 108: Testing the Next Generation

T E S T I N G A G A I N S T A M O D E L

Page 109: Testing the Next Generation

F S C H E C K W AY

Page 110: Testing the Next Generation

class FizzBuzzModel { public static string Translate(int value) { if (value % 15 == 0) return "FizzBuzz"; if (value % 3 == 0) return "Fizz"; if (value % 5 == 0) return "Buzz"; return value.ToString(CultureInfo.InvariantCulture); } } [TestCase] public void Will_Match_Model() { Spec.ForAny<int>(value => FizzBuzzModel.Translate(value).Equals(_fizzBuzzer.Translate(value))) .QuickCheckThrowOnFailure(); }

Page 111: Testing the Next Generation

class FizzBuzzModel { public static string Translate(int value) { if (value % 15 == 0) return "FizzBuzz"; if (value % 3 == 0) return "Fizz"; if (value % 5 == 0) return "Buzz"; return value.ToString(CultureInfo.InvariantCulture); } }

Page 112: Testing the Next Generation

[TestCase] public void Will_Match_Model() { Spec.ForAny<int>(value => FizzBuzzModel.Translate(value) .Equals(_fizzBuzzer.Translate(value))) .QuickCheckThrowOnFailure(); }

Page 113: Testing the Next Generation

Ok, passed 100 tests.

Page 114: Testing the Next Generation

H M M M M

Page 115: Testing the Next Generation

W E C O U L D U S E A S Y S T E M T O G E N E R AT E

D E G E N E R AT I V E T E S T D ATA T O D I S P L AY C O R R E C T N E S S

Page 116: Testing the Next Generation

M A K E I T S O .

Page 117: Testing the Next Generation

T E S T I N G N E G AT I O N

Page 118: Testing the Next Generation

F S C H E C K W AY

Page 119: Testing the Next Generation

[TestCase] public void Numbers_Not_Divisible_By_3_Do_Not_Fizz() { var noThrees = from number in Any.OfType<int>() where number%3 != 0 select number; Spec.For(noThrees, x => _fizzBuzzer.Translate(x) .Contains("Fizz") == false) .QuickCheckThrowOnFailure(); }

Page 120: Testing the Next Generation

Ok, passed 100 tests.

Page 121: Testing the Next Generation

[TestCase] public void Numbers_Not_Divisible_By_5_Do_Not_Buzz() { var noFives = from number in Any.OfType<int>() where number%5 != 0 select number; Spec.For(noFives, x => _fizzBuzzer.Translate(x) .Contains("Buzz") == false) .QuickCheckThrowOnFailure(); }

Page 122: Testing the Next Generation

Ok, passed 100 tests.

Page 123: Testing the Next Generation

H M M M M

Page 124: Testing the Next Generation

[TestCase] public void Numbers_Divisible_By_15_Must_FizzBuzz() { var onlyFifteens = from number in Any.OfType<int>() where number%15 == 0 select number; Spec.For(onlyFifteens, x => _fizzBuzzer.Translate(x) .Equals("FizzBuzz")) .QuickCheckThrowOnFailure(); }

Page 125: Testing the Next Generation

Ok, passed 100 tests.

Page 126: Testing the Next Generation

H M M M M

Page 127: Testing the Next Generation

[TestCase] public void Classify_Values() { Spec.ForAny<int>(x => true) .Classify( x => _fizzBuzzer.Translate(x).Equals("Fizz"), "Fizz") .Classify( x => _fizzBuzzer.Translate(x).Equals("Buzz"), "Buzz") .Classify(x => _fizzBuzzer.Translate(x).Equals("FizzBuzz"), "FizzBuzz") .Classify(x => _fizzBuzzer.Translate(x) != string.Empty, "Other") .QuickCheckThrowOnFailure(); }

Page 128: Testing the Next Generation

Ok, passed 100 tests. 55% Other. 22% Fizz, Other. 13% FizzBuzz, Other. 9% Buzz, Other.

Page 129: Testing the Next Generation

H M M M M

Page 130: Testing the Next Generation

[TestCase] public void Collect_Values_For_Negatives() { Spec.ForAny<int>(x => true) .When(x => x < 0) .Collect(x => _fizzBuzzer.Translate(x)) .QuickCheckThrowOnFailure(); }

Page 131: Testing the Next Generation

Ok, passed 100 tests.

Page 132: Testing the Next Generation

G R E AT !

Page 133: Testing the Next Generation
Page 134: Testing the Next Generation
Page 135: Testing the Next Generation
Page 136: Testing the Next Generation
Page 137: Testing the Next Generation
Page 138: Testing the Next Generation
Page 139: Testing the Next Generation

http://www.specflow.org/

specflow

Page 140: Testing the Next Generation

https://github.com/fsharp/FsCheck

fscheck

Page 141: Testing the Next Generation
Page 142: Testing the Next Generation

T H A N K Y O U

Page 143: Testing the Next Generation

M I K E H A R R I S @ M I K E M K H H T T P : / / C O M P - P H I L . B L O G S P O T. C O M /


Recommended