├── .gitignore ├── Demo1a-MockvsStub.1.ps1 ├── Demo1a-MockvsStub.ps1 ├── Demo1b-MockvsStub.ps1 ├── Demo2a-ScriptFiles.ps1 ├── Demo2b-ScriptFiles.ps1 ├── Demo3a-Binaries.ps1 ├── Demo4a-WebApis.ps1 ├── Demo4b-WebApis.ps1 ├── Demo5a-dotNet.ps1 ├── Demo6-Scriptblocks.ps1 ├── README.md ├── SlideOutline.md ├── Summit2017_Mocking.pptx └── lib ├── 1966_GT40s_LeMans_HR.jpg ├── 8f9ddae67fe3b50bdde857e69bab18ec.jpg ├── Demo1a.png ├── Demo1b.png ├── Demo2a.png ├── Demo2in.png ├── Demo2out.png ├── Demo3a.png ├── Demo3aResults.png ├── Demo3b.png ├── Demo4a.png ├── Demo4b.png ├── Demo5a.png ├── Demo5error.png ├── Demo5output.png ├── MockVsStub.png ├── StubCommand.png ├── ford-gt40-gulf-mirag-4_1600x0w.jpg └── goals_priciples_smells.png /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | ~\$Summit2017_Mocking\.pptx 3 | -------------------------------------------------------------------------------- /Demo1a-MockvsStub.1.ps1: -------------------------------------------------------------------------------- 1 | function MockMe ($Path) { 2 | return (Get-ChildItem -Path $Path -Filter "*.ps1") 3 | } 4 | 5 | Describe 'Mock' { # Behavior Verification 6 | Mock Get-ChildItem -ParameterFilter {$Path -eq 'C:\foo' -and $Filter -eq "*.ps1"} -MockWith {$null} 7 | Mock Get-ChildItem -ParameterFilter {$Path -eq 'C:\bar' -and $Filter -eq "*.ps1"} -MockWith {$null} 8 | 9 | Context 'Foo' { 10 | It 'Should only call GCI Foo' { 11 | $output = MockMe 'C:\foo' 12 | Assert-MockCalled Get-ChildItem -Times 1 -ParameterFilter {$Path -eq 'C:\foo' -and $Filter -eq "*.ps1"} 13 | } 14 | } 15 | 16 | Context 'Bar' { 17 | It 'Should only call GCI Bar' { 18 | $output = MockMe 'C:\bar' 19 | Assert-MockCalled Get-ChildItem -Times 1 -ParameterFilter {$Path -eq 'C:\foo' -and $Filter -eq "*.ps1"} 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Demo1a-MockvsStub.ps1: -------------------------------------------------------------------------------- 1 | function MockMe ($Path) { 2 | return (Get-ChildItem -Path $Path -Filter "*.ps1") 3 | } 4 | 5 | Describe 'Mock' { # Behavior Verification 6 | Mock Get-ChildItem -ParameterFilter {$Path -eq 'C:\foo' -and $Filter -eq "*.ps1"} -MockWith {$null} 7 | 8 | Context 'Foo' { 9 | It 'Should only call GCI Foo' { 10 | $output = MockMe 'C:\foo' 11 | Assert-MockCalled Get-ChildItem -Times 1 ` 12 | -ParameterFilter {$Path -eq 'C:\foo' -and $Filter -eq "*.ps1"} 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Demo1b-MockvsStub.ps1: -------------------------------------------------------------------------------- 1 | function StubMe ($Path) { 2 | 3 | $files = Get-ChildItem -Path $Path 4 | return ($files | Select-Object -First 1 -ExpandProperty Name) 5 | } 6 | 7 | Describe 'Stub' { # State Verification 8 | 9 | Mock Get-ChildItem -MockWith {[PSCustomObject]@{Name="test.txt" 10 | "LastWriteTime"=(Get-Date "2000-01-01")}} 11 | 12 | It 'Should return test.txt' { 13 | $output = StubMe C:\Whatever 14 | $output | Should Be 'test.txt' 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Demo2a-ScriptFiles.ps1: -------------------------------------------------------------------------------- 1 | Write-Output "Original File" -------------------------------------------------------------------------------- /Demo2b-ScriptFiles.ps1: -------------------------------------------------------------------------------- 1 | Describe 'Script File' { 2 | It 'Should call Demo2a-ScriptFiles.ps1' { 3 | 4 | ${function:C:\Source\TMGit\Chris.Hunt\pssummit2017-mocking\Demo2a-ScriptFiles.ps1}` 5 | = {Write-Output 'Testing'} 6 | 7 | $results = C:\Source\TMGit\Chris.Hunt\pssummit2017-mocking\Demo2a-ScriptFiles.ps1 8 | 9 | $results | Should Be 'Testing' 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /Demo3a-Binaries.ps1: -------------------------------------------------------------------------------- 1 | Describe 'Binaries' { 2 | Context 'LocalHost' { 3 | 4 | function ping { return @' 5 | Pinging LOCALHOST [::1] with 32 bytes of data: 6 | Reply from ::1: time<1ms 7 | Reply from ::1: time<1ms 8 | Ping statistics for ::1: 9 | Packets: Sent = 2, Received = 2, Lost = 0 (0% loss), 10 | Approximate round trip times in milli-seconds: 11 | Minimum = 0ms, Maximum = 0ms, Average = 0ms 12 | '@ 13 | } 14 | 15 | $results = ping localhost 16 | $results | Should Match '0% loss' 17 | } 18 | } 19 | 20 | 21 | Describe 'Binaries Again' { 22 | Context 'Psudo-Behavior Verificaiton' { 23 | 24 | function ping { return $args[0] } 25 | 26 | $results = ping remotehost 27 | $results | Should Be 'remotehost' 28 | 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /Demo4a-WebApis.ps1: -------------------------------------------------------------------------------- 1 | Import-Module flancy 2 | $url = "http://localhost:8001" 3 | New-Flancy -url $url -webschema @( 4 | Get '/' { "Api Mocks" } 5 | 6 | Post '/nodes/' { 7 | try { 8 | $body = (New-Object System.IO.StreamReader @($Request.Body, ` 9 | [System.Text.Encoding]::UTF8)).ReadToEnd() 10 | [PSCustomObject]@{Path=$Request.Path 11 | Headers=$Request.Headers 12 | Query=$Request.Query 13 | Method=$Request.Method 14 | Body=$body} | 15 | ConvertTo-Json -depth 2 } 16 | catch { $Error } } 17 | ) 18 | Start-Sleep -Seconds 1 19 | PING.EXE localhost -t 20 | 21 | 22 | -------------------------------------------------------------------------------- /Demo4b-WebApis.ps1: -------------------------------------------------------------------------------- 1 | Describe Nodes { 2 | $URI = "http://localhost:8001" 3 | Start-Job -Name ApiMocks -FilePath .\Demo4a-WebApis.ps1 4 | 5 | Context "Verify Flancy Server is running" { 6 | It "Should respond" { 7 | $results = Invoke-RestMethod $URI 8 | $results | Should Be "Api Mocks" 9 | } 10 | } 11 | 12 | Stop-Job -Name ApiMocks 13 | Remove-Job -Name ApiMocks 14 | } 15 | -------------------------------------------------------------------------------- /Demo5a-dotNet.ps1: -------------------------------------------------------------------------------- 1 | # Doesn't work 2 | $ps = New-Object -TypeName Diagnostics.Process -Property @{Name = "IMadeItUp.exe" 3 | ID = 321 4 | CPU = 50 5 | WorkingSet = 1MB} 6 | 7 | # But we can use PowerShell's Dynamic Type System 8 | $ps = New-Object -TypeName Diagnostics.Process | 9 | Add-Member ScriptProperty -Name ProcessName -Value {"IMadeItUp.exe"} -Force -PassThru | 10 | Add-Member ScriptProperty -Name ID -Value {321} -Force -PassThru | 11 | Add-Member ScriptMethod -Name Kill -Value {"Killed $($this.id)"} -Force -PassThru 12 | 13 | $ps 14 | $ps.kill() 15 | -------------------------------------------------------------------------------- /Demo6-Scriptblocks.ps1: -------------------------------------------------------------------------------- 1 | $scriptblock = [scriptblock]{ 2 | Get-Process 3 | } 4 | 5 | Describe 'ScriptBlock' { 6 | 7 | Mock Get-Process {'Mocked PS'} 8 | 9 | It 'Should Mock Get-Process' { 10 | $results = $scriptblock.Invoke() 11 | Assert-MockCalled Get-Process -Times 1 12 | } 13 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # You Can Mock Me As Much As You Like 2 | 3 | 4 | 5 | # Brain Dump 6 | 7 | Notes from presentaiton development. Does not mirror the contents of the slides. 8 | 9 | ## Definitions 10 | 11 | > Writing defect-free software is exceedingly difficult. Proof of correctness of real systems is still well beyond our abilities. 12 | > -- Gerard Meszaros, xUnit Test Patterns: Refactoring Test Code 13 | 14 | * Mock 15 | * Stub 16 | 17 | https://martinfowler.com/articles/mocksArentStubs.html 18 | 19 | >Meszaros uses the term **Test Double** as the generic term for *any kind of pretend object used in place of a real object for testing purposes*. 20 | >The name comes from the notion of a Stunt Double in movies. (One of his aims was to avoid using any name that was already widely used.) Meszaros then defined four particular kinds of double: 21 | > 22 | >**Dummy** objects are passed around but never actually used. 23 | >Usually they are just used to fill parameter lists. 24 | > 25 | >**Fake** objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example). 26 | > 27 | >**Stubs** provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. 28 | >Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messagesit 'sent'. 29 | > 30 | >**Mocks** objects pre-programmed with expectations which form a specification of the calls they are expected to receive. 31 | 32 | **System Under Test** (SUT), or rather the abbreviation SUT. 33 | 34 | **State Verification**: which means that we determine whether the exercised method worked correctly by examining the state of the SUT and its collaborators after the method was exercised 35 | 36 | > Mocks use **behavior verification**: check to see if the system made the correct calls 37 | > 38 | > [State Verification](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/ch21.html#ch21lev1sec1) (page [462](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/ch21.html#ch21lev1sec1)) is done using assertions and is the simpler of the two approaches. [Behavior Verification](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/ch21.html#ch21lev1sec2) (page [468](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/ch21.html#ch21lev1sec2)) is more complicated and builds on the assertion techniques we use for verifying state. 39 | 40 | **Depended-on Component** (DOC), An individual class or a large-grained component on which the system under test (SUT) depends.  41 | 42 | > The [**test fixture**](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/gloss01.html#gloss01_162) is everything we need to have in place to exercise the SUT. Typically, it includes at least an instance of the class whose method we are testing. 43 | 44 | [*xUnit Test Patterns: Refactoring Test Code* by Gerard Meszaros](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/) 45 | 46 | ### Quotes from *xUnit Test Patterns* 47 | 48 | #### Basics 49 | 50 | > ensuring that tests do not depend on anything they did not set up themselves 51 | 52 | > [Test Double](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/ch23.html#ch23lev1sec1)(page [522](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/ch23.html#ch23lev1sec1)) for the objects that act as interfaces to the other applications 53 | 54 | > functionally equivalent[Fake Objects](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/ch23.html#ch23lev1sec5) (page [551](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/ch23.html#ch23lev1sec5)) to speed up our tests 55 | 56 | #### Test Smells 57 | 58 | * **Project** smells are symptoms that something has gone wrong on the project. Their root cause is likely to be one or more of the code or behavior smells. 59 | 60 | * **Behavior** smells are encountered when we compile or run tests. The most common behavior smell is [Fragile Tests](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/ch16.html#ch16lev1sec3). It arises when tests that once passed begin failing for some reason. 61 | 62 | *  [Frequent Debugging](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/ch16.html#ch16lev1sec4) is a sign that the unit tests are lacking in coverage or are trying to test too much functionality at once. 63 | 64 | * **Code** smells...typically affect maintenance cost of tests, they may also be early warning signs of behavior smells to follow. 65 | 66 | *  Tests should be simple, linear sequences of statements.  67 | 68 | 69 | https://dev.to/ruidfigueiredo/what-exactly-is-a-unit-in-unit-testing 70 | 71 | #### Economics of Test Automation 72 | 73 | Ideal 74 | 75 | ![image](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/graphics/f03fig01.gif) 76 | 77 | * Goal: Tests as Specification 78 | * Goal: Bug Repellent 79 | * Goal: Defect Localization 80 | * Goal: Tests as Documentation 81 | * Goal: Tests as Safety Net 82 | * Goal: Do No Harm 83 | * Goal: Fully Automated Test 84 | * Goal: Self-Checking Test 85 | * Goal: Repeatable Test 86 | * Goal: Simple Tests 87 | * Goal: Expressive Tests 88 | * Goal: Separation of Concerns 89 | * Goal: Robust Test 90 | 91 | > #### Tests Should Help Us Understand the SUT 92 | 93 | > a library of [Test Utility Methods](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/ch24.html#ch24lev1sec2) that constitute a domain-specific testing language 94 | 95 | [Test Automation Manfiesto](http://xunitpatterns.com/~gerard/xpau2003-test-automation-manifesto-paper.pdf) 96 | 97 | ## What to Mock and When 98 | 99 | ![](/lib/goals_priciples_smells.png) 100 | 101 | 102 | 103 | ####  Use the Front Door First 104 | 105 | Use the interface the client is expected to use. 106 | 107 | **Figure 6.7.** A round-trip test interacts with the SUT only via the front door. The test on the right replaces a DOC with a Fake Object to improve its repeatability or performance. 108 | 109 | ![image](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/graphics/f06fig07.gif) 110 | 111 | **Figure 6.8.** A layer-crossing test can interact with the SUT via a "back door." The test on the left controls the SUT's indirect inputs using a Test Stub. The test on the right verifies its indirect outputs using a Mock Object. 112 | 113 | ![image](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/graphics/f06fig08.gif) 114 | 115 | **Figure 6.10.** A Test Double being "injected" into a SUT by a test. A test can use Dependency Injection to replace a DOC with an appropriate Test Double. The DOC is passed to the SUT by the test as or after it has been created. 116 | 117 | ![image](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/graphics/f06fig10.gif) 118 | 119 | #### Don't Modify the SUT 120 | 121 | May use a test double to control input and output and avoid unacceptable side effects. 122 | 123 | ### Four distinct phases 124 | 125 | fixture setup, exercise SUT, result verification, and fixture teardown. 126 | 127 | ![image](https://www.safaribooksonline.com/library/view/xunit-test-patterns/9780131495050/graphics/f06fig06.gif) 128 | 129 | 130 | ## Mock script file invocation 131 | jaykul [11/18 10:14 AM] TIL how to mock script files: 132 | ${function:C:\Users\joel.bennett\script.ps1}={Write-Host "All Clear" -Fore Green} 133 | 134 | ## Mock Return type 135 | Mock Function { [PSCustomObject]@{ PSTypeName = 'Microsoft.UpdateServices.Internal.BaseApi.UpdateServer' } } 136 | 137 | or you might be able to mock the function that gets the object to return a mocked object 138 | 139 | ## Mock native commands 140 | 141 | ``` powershell 142 | function ping { return @' 143 | Pinging USHOLCHU1-L.LYV.LiveNation.com [::1] with 32 bytes of data: 144 | Reply from ::1: time<1ms 145 | Reply from ::1: time<1ms 146 | Ping statistics for ::1: 147 | Packets: Sent = 2, Received = 2, Lost = 0 (0% loss), 148 | Approximate round trip times in milli-seconds: 149 | Minimum = 0ms, Maximum = 0ms, Average = 0ms 150 | '@ 151 | } 152 | ``` 153 | 154 | ## Mock Web APIs 155 | 156 | Mock Invoke-RestMethod 157 | Spin up PowerShell based web service 158 | 159 | ## Mocking ScriptBlocks?? -------------------------------------------------------------------------------- /SlideOutline.md: -------------------------------------------------------------------------------- 1 | # Intro 2 | 3 | ## You Can Mock Me As Much As You Like 4 | 5 | Chris Hunt 6 | 7 | Windows Platform Engineer at Ticketmaster 8 | 9 | @LogicalDiagram 10 | 11 | https://github.com/cdhunt 12 | 13 | ## Why we are here 14 | 15 | > Writing defect-free software is exceedingly difficult. Proof of correctness of real systems is still well beyond our abilities. 16 | > 17 | > -- Gerard Meszaros, xUnit Test Patterns: Refactoring Test Code 18 | 19 | - You want to write better PowerShell 20 | - You want to build and use unit tests 21 | - Pester has a `Mock` command, but you're not sure when you should use it. 22 | - You are testing code that calls something that isn't a PowerShell function and `Mock` doesn't work 23 | 24 | ## Starting Point 25 | 26 | Let's assume: 27 | 28 | * You have a basic understanding of Pester 29 | * You are convinced that writing unit test are the way to go 30 | * You will likely walk away realizing we've only scratched the surface 31 | 32 | # Let's start with the correct vocabulary 33 | 34 | We use the term **Mock** generically when there are lot of different way to make fake things. Gerard Meszaros uses the term **Test Double** for **any kind of pretend object used in place of a real object for testing purposes**. 35 | 36 | **Dummy Object** An object that is passed around but never used. 37 | 38 | **Fake Object** A working object, but takes some shortcuts. Example: Hard codes some properties instead of pulls them from an external source. 39 | 40 | **Stubs** Provide static responses to calls made during the test. 41 | 42 | **Mocks** Functions pre-programmed with expectations which form a specification of the calls they are expected to receive. 43 | 44 | ### Some More Definitions 45 | 46 | **System Under Test** (SUT) - a single unit of work you are testing 47 | 48 | **State Verification** Determine whether a test passed based on the state of the SUT after execution. `{1 -eq 1} | Should Be $true` 49 | 50 | **Behavior Verification** Determine whether a test passed based on the calls made during execution. `Assert-MockCalled`, `Should Throw` 51 | 52 | **Depended-on Component** (DOC) An individual class or a large-grained component on which the system under test (SUT) depends. 53 | 54 | ## Cool, but not 1-to-1 in PowerShell 55 | 56 | PowerShell is a crazy dynamic language. 57 | 58 | # A short story 59 | 60 | In 1963 Ford wanted a car at Le Mans and heard Enzo Ferrari was willing to sell. After a great deal of due diligance by Ford, Ferrari walked out when he found out Ford refused to let him remain in control of the racing division. Ford was now determined to beat Ferrari and outsourced development of a race car to company based in England. The result was the GT40. 61 | 62 | ![](http://pictures.topspeed.com/IMG/crop/201208/ford-gt40-gulf-mirag-4_1600x0w.jpg) 63 | 64 | In 1964, Despite setting a lap, record all three GT40s failed to finish and Ferrari won. 65 | 66 | After the 1964 season, Ford brought in Carrol Shelby to take over the GT40 program. 67 | 68 | In 1965, two GT40's were entered and both failed to finish and Ferrari won. 69 | 70 | After 1965 Ford built a dynamometer laboratory to automate the testing of the engines as closely as possible to on-course conditions. 71 | 72 | ![chrome_2017-03-17_13-09-39](C:\Users\chris.hunt\Documents\ShareX\Screenshots\2017-03\chrome_2017-03-17_13-09-39.png) 73 | 74 | [Ford Dyno Testing](https://youtu.be/NxP__UPj7L8) 75 | 76 | In 1966, the GT40's finished 1-2-3. 77 | 78 | ![](https://assets.hemmings.com/blog/wp-content/uploads//2015/01/1966_GT40s_LeMans_HR.jpg) 79 | 80 | ## Just like the GT40 program 81 | 82 | * We isolate one component and try simulate real world conditions 83 | * Testing one component allows us to improve faster and cheaper than building and testing the entire product 84 | 85 | # Learn by Example 86 | 87 | ## Mock 88 | 89 | ```powershell 90 | Mock Function -Parameters @{'A'='B'} 91 | Mock Function -Parameters @{'A'='C'} 92 | Asset-MockCalled -Parameters @{'A'='C'} 93 | ``` 94 | 95 | ## Dummy Objects 96 | 97 | ```powershell 98 | get-example 1 99 | ``` 100 | 101 | ```powershell 102 | get-example 2 103 | ``` 104 | 105 | ## Fake Object 106 | 107 | ## Stub -------------------------------------------------------------------------------- /Summit2017_Mocking.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/Summit2017_Mocking.pptx -------------------------------------------------------------------------------- /lib/1966_GT40s_LeMans_HR.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/1966_GT40s_LeMans_HR.jpg -------------------------------------------------------------------------------- /lib/8f9ddae67fe3b50bdde857e69bab18ec.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/8f9ddae67fe3b50bdde857e69bab18ec.jpg -------------------------------------------------------------------------------- /lib/Demo1a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/Demo1a.png -------------------------------------------------------------------------------- /lib/Demo1b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/Demo1b.png -------------------------------------------------------------------------------- /lib/Demo2a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/Demo2a.png -------------------------------------------------------------------------------- /lib/Demo2in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/Demo2in.png -------------------------------------------------------------------------------- /lib/Demo2out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/Demo2out.png -------------------------------------------------------------------------------- /lib/Demo3a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/Demo3a.png -------------------------------------------------------------------------------- /lib/Demo3aResults.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/Demo3aResults.png -------------------------------------------------------------------------------- /lib/Demo3b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/Demo3b.png -------------------------------------------------------------------------------- /lib/Demo4a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/Demo4a.png -------------------------------------------------------------------------------- /lib/Demo4b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/Demo4b.png -------------------------------------------------------------------------------- /lib/Demo5a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/Demo5a.png -------------------------------------------------------------------------------- /lib/Demo5error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/Demo5error.png -------------------------------------------------------------------------------- /lib/Demo5output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/Demo5output.png -------------------------------------------------------------------------------- /lib/MockVsStub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/MockVsStub.png -------------------------------------------------------------------------------- /lib/StubCommand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/StubCommand.png -------------------------------------------------------------------------------- /lib/ford-gt40-gulf-mirag-4_1600x0w.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/ford-gt40-gulf-mirag-4_1600x0w.jpg -------------------------------------------------------------------------------- /lib/goals_priciples_smells.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdhunt/pssummit2017-mocking/685f1599c39e1066230db3e20971d59f82bb4f07/lib/goals_priciples_smells.png --------------------------------------------------------------------------------