# Roy Osherove Courses: full text > A free archive of Roy Osherove's classic courses, which he used to teach live: 6 courses with 99 video lessons on unit testing, TDD, legacy code and Vim. Every lesson is a YouTube video. Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page). License: https://creativecommons.org/licenses/by/4.0/. Source: https://courses.osherove.com/ . Generated 2026-10-23T23:06:26.798Z. 0 posts, 108 pages. ## About the author **Roy Osherove**: Senior Solutions Architect at AWS working on AI for production and AI-driven development; author of The Art of Unit Testing and Elastic Leadership, with about 20 years of consulting and training on unit testing, TDD, team leadership and continuous delivery. ### Sites - [RobotPaper](https://robotpaper.ai/): This blog: AI patterns and anti-patterns, AI and coding agents, and engineering leadership. - [osherove.com](https://osherove.com): Roy's personal site. Author of The Art of Unit Testing and Elastic Leadership; consulting and training on unit testing, TDD, team leadership and continuous delivery, plus about 20 years of blog posts. - [The Art of Unit Testing](https://www.artofunittesting.com): The Art of Unit Testing, 3rd Edition (Manning): readable, maintainable, trustworthy unit tests, plus TDD workshops in C#, JavaScript, Java and Kotlin. - [5whys.com](https://www.5whys.com): Roy's writing on software team leadership: self-organizing teams, surviving chaos, learning mode and the Elastic Leadership model. - [Pipeline Driven](https://pipelinedriven.org): Continuous delivery and DevOps practices: build patterns, pipeline-friendly testing, DevOps metrics and enterprise DevOps. - [Elastic Leadership](https://www.elasticleadership.com): Elastic Leadership, Roy's framework for software team leaders (survival, learning and self-organizing modes). ### Social - X: https://x.com/royosherove - LinkedIn: https://www.linkedin.com/in/osherove/ ### Contact - Contact form: https://forms.gle/jQSx5KoXvrVA1JCK7 ### License Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page). License: https://creativecommons.org/licenses/by/4.0/ --- title: "Roy Osherove Courses" url: "https://courses.osherove.com/index.md" canonical: "https://courses.osherove.com/" tags: [] author: "Roy Osherove" description: "Roy Osherove's classic video courses on unit testing, TDD, legacy code and Vim, free for everyone. Watch every lesson on YouTube." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Roy Osherove Courses > A free archive of Roy Osherove's classic courses, which he used to teach live: 6 courses with 99 video lessons on unit testing, TDD, legacy code and Vim. Every lesson is a YouTube video. HTML: https://courses.osherove.com/ · Guide for AI systems: [llms.txt](https://courses.osherove.com/llms.txt) · Full text: [llms-full.txt](https://courses.osherove.com/llms-full.txt) ## On the home page Free video courses by Roy Osherove Roy Osherove's classic courses on unit testing, TDD, legacy code and more, free for everyone. - **6** courses - **99** lessons - **36 h 30 min** of video #### Courses Every lesson plays here or on YouTube. - ![](https://courses.osherove.com/img/yt/WWZR6vq6BvU.jpg) ### [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 14 lessons 9 h 6 min 5 sections - ![](https://courses.osherove.com/img/yt/jLDdx00oDU4.jpg) ### [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 21 lessons 3 h 38 min 3 sections - ![](https://courses.osherove.com/img/yt/8riX4rG7Idc.jpg) ### [TDD Pairing Sessions - Building a Go Game](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/) 11 lessons 10 h 50 min - ![](https://courses.osherove.com/img/yt/gtRXDuLj8uc.jpg) ### [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 22 lessons 7 h 44 min 5 sections Spoken in Hebrew - ![](https://courses.osherove.com/img/yt/XCS-9_kC6Kw.jpg) ### [Legacy Code Hero](https://courses.osherove.com/courses/legacy-code-hero/) 5 lessons 2 h 56 min 2 sections - ![](https://courses.osherove.com/img/yt/8vwMvLf0bPI.jpg) ### [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 26 lessons 2 h 16 min 5 sections ## Pages - [About](https://courses.osherove.com/about.md): About Roy Osherove Courses: Roy Osherove's classic courses, which he used to teach live, now free for everyone on YouTube. - [Privacy](https://courses.osherove.com/privacy.md): Privacy on Roy Osherove Courses: what Google Analytics and Cloudflare Web Analytics collect, how to opt out, and no ads. ## The Art of Unit Testing & TDD Master Class in .NET - [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net.md): The Art of Unit Testing & TDD Master Class in .NET: 14 lessons, 9 h 6 min. A free video course by Roy Osherove. - [Unit Testing And TDD 101](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/unit-testing-and-tdd-101.md): Lesson 1 of 14 in The Art of Unit Testing & TDD Master Class in .NET (The Basics), 1:55:52. Free video by Roy Osherove. - [Test Driving a String Calculator](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-driving-a-string-calculator.md): Lesson 2 of 14 in The Art of Unit Testing & TDD Master Class in .NET (The Basics), 27:29. Free video by Roy Osherove. - [Test Driving a Console Application Using String Calculator](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-driving-a-console-application-using-string-calculator.md): Lesson 3 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Fakes, Mocks and Stubs), 16:54. Free video by Roy Osherove. - [Introduction to Hand Written Fakes, Mocks and Stubs](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/introduction-to-hand-written-fakes-mocks-and-stubs.md): Lesson 4 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Fakes, Mocks and Stubs), 7:18. Free video by Roy Osherove. - [Isolation Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/isolation-frameworks.md): Lesson 5 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Fakes, Mocks and Stubs), 1:01:27. Free video by Roy Osherove. - [Test Review Practices](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-review-practices.md): Lesson 6 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Test Review Insights), 1:00:31. Free video by Roy Osherove. - [NerdDinner Test Review](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/nerddinner-test-review.md): Lesson 7 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Test Review Insights), 27:17. Free video by Roy Osherove. - [Unity Test Review](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/unity-test-review.md): Lesson 8 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Test Review Insights), 25:37. Free video by Roy Osherove. - [Using Extract & Override](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/using-extract-and-override.md): Lesson 9 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Legacy Code), 21:33. Free video by Roy Osherove. - [Static Forwarding on a real legacy app](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/static-forwarding-on-a-real-legacy-app.md): Lesson 10 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Legacy Code), 13:44. Free video by Roy Osherove. - [Testing Legacy Code with Typemock Isolator Deep Dive](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/testing-legacy-code-with-typemock-isolator-deep-dive.md): Lesson 11 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Legacy Code), 20:08. Free video by Roy Osherove. - [Code Excavations and Domain Specific Test Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/code-excavations-and-domain-specific-test-frameworks.md): Lesson 12 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Bonus tracks on advanced patterns), 54:14. Free video by Roy Osherove. - [Testing Complex Validation Knowledge using Extract & Override](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/testing-complex-validation-knowledge-using-extract-and-override.md): Lesson 13 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Bonus tracks on advanced patterns), 43:35. Free video by Roy Osherove. - [Mocking On The Edge](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/mocking-on-the-edge.md): Lesson 14 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Bonus tracks on advanced patterns), 49:54. Free video by Roy Osherove. ## The Art of Unit Testing and TDD in Java - [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java.md): The Art of Unit Testing and TDD in Java: 21 lessons, 3 h 38 min. A free video course by Roy Osherove. - [Introduction to Unit Testing Ideas](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-unit-testing-ideas.md): Lesson 1 of 21 in The Art of Unit Testing and TDD in Java (Day 1), 28:25. Free video by Roy Osherove. - [Introduction to JUnit](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-junit.md): Lesson 2 of 21 in The Art of Unit Testing and TDD in Java (Day 1), 13:48. Free video by Roy Osherove. - [Unit Testing Demo](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/unit-testing-demo.md): Lesson 3 of 21 in The Art of Unit Testing and TDD in Java (Day 1), 7:30. Free video by Roy Osherove. - [Introducing TDD](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introducing-tdd.md): Lesson 4 of 21 in The Art of Unit Testing and TDD in Java (Day 1), 12:53. Free video by Roy Osherove. - [Simplicity is Complicated](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/simplicity-is-complicated.md): Lesson 5 of 21 in The Art of Unit Testing and TDD in Java (Day 1), 11:37. Free video by Roy Osherove. - [Common TDD Questions and Answers](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/common-tdd-questions-and-answers.md): Lesson 6 of 21 in The Art of Unit Testing and TDD in Java (Day 1), 5:49. Free video by Roy Osherove. - [Some Numbers](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/some-numbers.md): Lesson 7 of 21 in The Art of Unit Testing and TDD in Java (Day 1), 5:37. Free video by Roy Osherove. - [Introduction to Mocks and Stubs](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-mocks-and-stubs.md): Lesson 8 of 21 in The Art of Unit Testing and TDD in Java (Day 2), 10:30. Free video by Roy Osherove. - [Demo - Mock Objects](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/demo-mock-objects.md): Lesson 9 of 21 in The Art of Unit Testing and TDD in Java (Day 2), 9:17. Free video by Roy Osherove. - [Terminology](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/terminology.md): Lesson 10 of 21 in The Art of Unit Testing and TDD in Java (Day 2), 0:56. Free video by Roy Osherove. - [Mocks And Stubs](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/mocks-and-stubs.md): Lesson 11 of 21 in The Art of Unit Testing and TDD in Java (Day 2), 8:43. Free video by Roy Osherove. - [Isolation (Mocking) Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/isolation-mocking-frameworks.md): Lesson 12 of 21 in The Art of Unit Testing and TDD in Java (Day 2), 19:53. Free video by Roy Osherove. - [Capturing Mock Arguments](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/capturing-mock-arguments.md): Lesson 13 of 21 in The Art of Unit Testing and TDD in Java (Day 2), 4:36. Free video by Roy Osherove. - [Extract And Override Refactoring](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/extract-and-override-refactoring.md): Lesson 14 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 13:35. Free video by Roy Osherove. - [Faking Time](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/faking-time.md): Lesson 15 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 5:46. Free video by Roy Osherove. - [Faking Futures](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/faking-futures.md): Lesson 16 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 2:41. Free video by Roy Osherove. - [Unconstrained Isolation Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/unconstrained-isolation-frameworks.md): Lesson 17 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 9:50. Free video by Roy Osherove. - [Throw Errors with Powermock](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/throw-errors-with-powermock.md): Lesson 18 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 1:21. Free video by Roy Osherove. - [Discussion About Pros and Cons of Unconstrained Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/discussion-about-pros-and-cons-of-unconstrained-frameworks.md): Lesson 19 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 2:14. Free video by Roy Osherove. - [Continuous Delivery](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/continuous-delivery.md): Lesson 20 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 42:33. Free video by Roy Osherove. - [Summary](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/summary.md): Lesson 21 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 0:35. Free video by Roy Osherove. ## TDD Pairing Sessions - Building a Go Game - [TDD Pairing Sessions - Building a Go Game](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game.md): TDD Pairing Sessions - Building a Go Game: 11 lessons, 10 h 50 min. A free video course by Roy Osherove. - [Understanding the Problem](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/understanding-the-problem.md): Lesson 1 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 1:53:39. Free video by Roy Osherove. - [Mapping Moves](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/mapping-moves.md): Lesson 2 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 30:05. Free video by Roy Osherove. - [Stoned and Board](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/stoned-and-board.md): Lesson 3 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 30:14. Free video by Roy Osherove. - [Colors and Winners](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/colors-and-winners.md): Lesson 4 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 48:10. Free video by Roy Osherove. - [Finding a Winner](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/finding-a-winner.md): Lesson 5 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 1:01:59. Free video by Roy Osherove. - [Total Noob Fail](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/total-noob-fail.md): Lesson 6 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 1:26:57. Free video by Roy Osherove. - [A DSL for our Tests](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/a-dsl-for-our-tests.md): Lesson 7 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 55:07. Free video by Roy Osherove. - [A Refactoring Dillemma](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/a-refactoring-dillemma.md): Lesson 8 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 43:47. Free video by Roy Osherove. - [Debugging Excursions](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/debugging-excursions.md): Lesson 9 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 51:29. Free video by Roy Osherove. - [The Big Refactor](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/the-big-refactor.md): Lesson 10 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 1:28:13. Free video by Roy Osherove. - [New Features](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/new-features.md): Lesson 11 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 40:06. Free video by Roy Osherove. ## TDD in .NET in Hebrew - [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew.md): TDD in .NET in Hebrew: 22 lessons, 7 h 44 min. A free video course by Roy Osherove. - [Introduction](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/introduction.md): Lesson 1 of 22 in TDD in .NET in Hebrew (Day1 - Unit Testing and TDD 101), 33:07. Free video by Roy Osherove. - [Syntax](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/syntax.md): Lesson 2 of 22 in TDD in .NET in Hebrew (Day1 - Unit Testing and TDD 101), 29:43. Free video by Roy Osherove. - [Test Demo](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/test-demo.md): Lesson 3 of 22 in TDD in .NET in Hebrew (Day1 - Unit Testing and TDD 101), 34:54. Free video by Roy Osherove. - [Test Cases, String Asserts and more](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/test-cases-string-asserts-and-more.md): Lesson 4 of 22 in TDD in .NET in Hebrew (Day1 - Unit Testing and TDD 101), 34:49. Free video by Roy Osherove. - [TDD Demo](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/tdd-demo.md): Lesson 5 of 22 in TDD in .NET in Hebrew (Day1 - Unit Testing and TDD 101), 19:26. Free video by Roy Osherove. - [Summary Day 1](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/summary-day-1.md): Lesson 6 of 22 in TDD in .NET in Hebrew (Day1 - Unit Testing and TDD 101), 8:45. Free video by Roy Osherove. - [TDD Q & A](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/tdd-q-and-a.md): Lesson 7 of 22 in TDD in .NET in Hebrew (Day 2 - Mock Objects and TDD), 35:14. Free video by Roy Osherove. - [Mocks and Stubs](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/mocks-and-stubs.md): Lesson 8 of 22 in TDD in .NET in Hebrew (Day 2 - Mock Objects and TDD), 24:52. Free video by Roy Osherove. - [Isolation Frameworks](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/isolation-frameworks.md): Lesson 9 of 22 in TDD in .NET in Hebrew (Day 2 - Mock Objects and TDD), 34:31. Free video by Roy Osherove. - [Advanced Mocks and Stubs](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/advanced-mocks-and-stubs.md): Lesson 10 of 22 in TDD in .NET in Hebrew (Day 2 - Mock Objects and TDD), 12:50. Free video by Roy Osherove. - [Recursive Fakes](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/recursive-fakes.md): Lesson 11 of 22 in TDD in .NET in Hebrew (Day 2 - Mock Objects and TDD), 3:10. Free video by Roy Osherove. - [Legacy Refactoring intro](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/legacy-refactoring-intro.md): Lesson 12 of 22 in TDD in .NET in Hebrew (Day 2 - Legacy Code Tools), 16:23. Free video by Roy Osherove. - [Controlling Time](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/controlling-time.md): Lesson 13 of 22 in TDD in .NET in Hebrew (Day 2 - Legacy Code Tools), 6:44. Free video by Roy Osherove. - [Working with Typemock Isolator](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/working-with-typemock-isolator.md): Lesson 14 of 22 in TDD in .NET in Hebrew (Day 2 - Legacy Code Tools), 26:41. Free video by Roy Osherove. - [Day 2 Summary](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/day-2-summary.md): Lesson 15 of 22 in TDD in .NET in Hebrew (Day 2 - Legacy Code Tools), 2:23. Free video by Roy Osherove. - [Unit Testing Best Practices](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/unit-testing-best-practices.md): Lesson 16 of 22 in TDD in .NET in Hebrew (Day 3 - Unit Testing Practices), 35:00. Free video by Roy Osherove. - [Best Practices Continued](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/best-practices-continued.md): Lesson 17 of 22 in TDD in .NET in Hebrew (Day 3 - Unit Testing Practices), 25:20. Free video by Roy Osherove. - [Maintainability Practices](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/maintainability-practices.md): Lesson 18 of 22 in TDD in .NET in Hebrew (Day 3 - Unit Testing Practices), 34:43. Free video by Roy Osherove. - [Readability Practices](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/readability-practices.md): Lesson 19 of 22 in TDD in .NET in Hebrew (Day 3 - Unit Testing Practices), 1:23. Free video by Roy Osherove. - [Legacy BlogEngine Project Overview](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/legacy-blogengine-project-overview.md): Lesson 20 of 22 in TDD in .NET in Hebrew (Day 3 - Legacy Code), 8:02. Free video by Roy Osherove. - [Refactoring- Introduce Instance Delegator](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/refactoring-introduce-instance-delegator.md): Lesson 21 of 22 in TDD in .NET in Hebrew (Day 3 - Legacy Code), 17:36. Free video by Roy Osherove. - [Summary and Discussion Day 3](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/summary-and-discussion-day-3.md): Lesson 22 of 22 in TDD in .NET in Hebrew (Day 3 - Legacy Code), 18:48. Free video by Roy Osherove. ## Legacy Code Hero - [Legacy Code Hero](https://courses.osherove.com/courses/legacy-code-hero.md): Legacy Code Hero: 5 lessons, 2 h 56 min. A free video course by Roy Osherove. - [Where Do You Start with Legacy Code?](https://courses.osherove.com/courses/legacy-code-hero/where-do-you-start-with-legacy-code.md): Lesson 1 of 5 in Legacy Code Hero (Starting Out), 50:03. Free video by Roy Osherove. - [Refactoring Hardcore Skills](https://courses.osherove.com/courses/legacy-code-hero/refactoring-hardcore-skills.md): Lesson 2 of 5 in Legacy Code Hero (Refactoring), 46:58. Free video by Roy Osherove. - [Instance Delegator Focus](https://courses.osherove.com/courses/legacy-code-hero/instance-delegator-focus.md): Lesson 3 of 5 in Legacy Code Hero (Refactoring), 13:44. Free video by Roy Osherove. - [Extract And Override Focus](https://courses.osherove.com/courses/legacy-code-hero/extract-and-override-focus.md): Lesson 4 of 5 in Legacy Code Hero (Refactoring), 21:17. Free video by Roy Osherove. - [Extract And Override With Validation Logic](https://courses.osherove.com/courses/legacy-code-hero/extract-and-override-with-validation-logic.md): Lesson 5 of 5 in Legacy Code Hero (Refactoring), 43:35. Free video by Roy Osherove. ## Vim Hates You - [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you.md): Vim Hates You: 26 lessons, 2 h 16 min. A free video course by Roy Osherove. - [Why Vim?](https://courses.osherove.com/courses/vim-hates-you/why-vim.md): Lesson 1 of 26 in Vim Hates You (Get some context), 8:46. Free video by Roy Osherove. - [Vim file open save, load, moving, changing and selecting text](https://courses.osherove.com/courses/vim-hates-you/vim-file-open-save-load-moving-changing-and-selecting-text.md): Lesson 2 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 7:04. Free video by Roy Osherove. - [Copying, Pasting and Yanking in Vim](https://courses.osherove.com/courses/vim-hates-you/copying-pasting-and-yanking-in-vim.md): Lesson 3 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 3:30. Free video by Roy Osherove. - [Syntax Highlighting and Numbering in .vimrc file](https://courses.osherove.com/courses/vim-hates-you/syntax-highlighting-and-numbering-in-vimrc-file.md): Lesson 4 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 2:41. Free video by Roy Osherove. - [Basic Searching inside a file in VIM](https://courses.osherove.com/courses/vim-hates-you/basic-searching-inside-a-file-in-vim.md): Lesson 5 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 2:42. Free video by Roy Osherove. - [Indentation](https://courses.osherove.com/courses/vim-hates-you/indentation.md): Lesson 6 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 3:31. Free video by Roy Osherove. - [Understanding Vim Modes and Block Selection Magic](https://courses.osherove.com/courses/vim-hates-you/understanding-vim-modes-and-block-selection-magic.md): Lesson 7 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 6:13. Free video by Roy Osherove. - [Color Schemes](https://courses.osherove.com/courses/vim-hates-you/color-schemes.md): Lesson 8 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 6:20. Free video by Roy Osherove. - [Basic Search and Replace in a file](https://courses.osherove.com/courses/vim-hates-you/basic-search-and-replace-in-a-file.md): Lesson 9 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 4:41. Free video by Roy Osherove. - [Search and Replace with Regex](https://courses.osherove.com/courses/vim-hates-you/search-and-replace-with-regex.md): Lesson 10 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 3:20. Free video by Roy Osherove. - [Useful Vim Commands Reference](https://courses.osherove.com/courses/vim-hates-you/useful-vim-commands-reference.md): Lesson 11 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 18:06. Free video by Roy Osherove. - [Vim Shortcuts in Bash and ZSH](https://courses.osherove.com/courses/vim-hates-you/vim-shortcuts-in-bash-and-zsh.md): Lesson 12 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 1:36. Free video by Roy Osherove. - [Multiple Windows](https://courses.osherove.com/courses/vim-hates-you/multiple-windows.md): Lesson 13 of 26 in Vim Hates You (Divide & Conquer your windows), 3:07. Free video by Roy Osherove. - [Vim Tabs](https://courses.osherove.com/courses/vim-hates-you/vim-tabs.md): Lesson 14 of 26 in Vim Hates You (Divide & Conquer your windows), 2:10. Free video by Roy Osherove. - [Tabs as window Layouts](https://courses.osherove.com/courses/vim-hates-you/tabs-as-window-layouts.md): Lesson 15 of 26 in Vim Hates You (Divide & Conquer your windows), 2:25. Free video by Roy Osherove. - [Installing Plugins (Vim plug + Airline)](https://courses.osherove.com/courses/vim-hates-you/installing-plugins-vim-plug-airline.md): Lesson 16 of 26 in Vim Hates You (Bring in reinforcements - Plugins), 8:57. Free video by Roy Osherove. - [NerdTree in Vim](https://courses.osherove.com/courses/vim-hates-you/nerdtree-in-vim.md): Lesson 17 of 26 in Vim Hates You (Bring in reinforcements - Plugins), 3:39. Free video by Roy Osherove. - [Ctrl-P](https://courses.osherove.com/courses/vim-hates-you/ctrl-p.md): Lesson 18 of 26 in Vim Hates You (Bring in reinforcements - Plugins), 2:47. Free video by Roy Osherove. - [Find text in multiple files with AG](https://courses.osherove.com/courses/vim-hates-you/find-text-in-multiple-files-with-ag.md): Lesson 19 of 26 in Vim Hates You (Bring in reinforcements - Plugins), 6:05. Free video by Roy Osherove. - [Mapping keys to actions](https://courses.osherove.com/courses/vim-hates-you/mapping-keys-to-actions.md): Lesson 20 of 26 in Vim Hates You (Go Faster), 8:22. Free video by Roy Osherove. - [Mapping Leaders in Vim](https://courses.osherove.com/courses/vim-hates-you/mapping-leaders-in-vim.md): Lesson 21 of 26 in Vim Hates You (Go Faster), 3:57. Free video by Roy Osherove. - [Edit and source your .Vimrc faster](https://courses.osherove.com/courses/vim-hates-you/edit-and-source-your-vimrc-faster.md): Lesson 22 of 26 in Vim Hates You (Go Faster), 4:54. Free video by Roy Osherove. - [Understanding Vim Registers](https://courses.osherove.com/courses/vim-hates-you/understanding-vim-registers.md): Lesson 23 of 26 in Vim Hates You (Go Faster), 8:37. Free video by Roy Osherove. - [Vim and the System Clipboard](https://courses.osherove.com/courses/vim-hates-you/vim-and-the-system-clipboard.md): Lesson 24 of 26 in Vim Hates You (Go Faster), 4:57. Free video by Roy Osherove. - [Abbreviations in Vim](https://courses.osherove.com/courses/vim-hates-you/abbreviations-in-vim.md): Lesson 25 of 26 in Vim Hates You (Go Faster), 2:25. Free video by Roy Osherove. - [VIm Macros](https://courses.osherove.com/courses/vim-hates-you/vim-macros.md): Lesson 26 of 26 in Vim Hates You (Go Faster), 5:37. Free video by Roy Osherove. --- title: "About" url: "https://courses.osherove.com/about.md" canonical: "https://courses.osherove.com/about/" tags: [] author: "Roy Osherove" description: "About Roy Osherove Courses: Roy Osherove's classic courses, which he used to teach live, now free for everyone on YouTube." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # About About # About these courses These are Roy Osherove’s classic courses, which he used to teach live. They are now free for everyone. All 6 courses and 99 lessons are here, in their original order and with their original titles. Every lesson is a video on YouTube: play it on the lesson page or open it on YouTube. - [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) - [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) - [TDD Pairing Sessions - Building a Go Game](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/) - [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) - [Legacy Code Hero](https://courses.osherove.com/courses/legacy-code-hero/) - [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) ## More from Roy Roy’s website: [osherove.com](https://osherove.com/). His YouTube channel: [Roy on YouTube](https://www.youtube.com/channel/UCM9Jz0z1IXlgGy_CY3wGRWA). ## Contact To reach Roy, use the [contact form](https://forms.gle/jQSx5KoXvrVA1JCK7). --- title: "Privacy" url: "https://courses.osherove.com/privacy.md" canonical: "https://courses.osherove.com/privacy/" tags: [] author: "Roy Osherove" description: "Privacy on Roy Osherove Courses: what Google Analytics and Cloudflare Web Analytics collect, how to opt out, and no ads." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Privacy Privacy This site counts visits with two analytics tools so Roy Osherove can see which courses people watch. It shows no ads, sells nothing and has no accounts. Last updated: 24 October 2026. ## Google Analytics 4 Google Analytics records (with its standard settings) the pages you view, the page that linked you here, search words that are part of a page address (see Search below), clicks on links to other sites, scrolling, how long a page is open, your browser, device type, operating system, screen size and language, and your approximate location (country, region and city, which Google works out from your IP address; Google Analytics 4 does not store IP addresses). It sets two first-party cookies, `_ga` and `_ga_…`, which hold a random ID so a returning browser is counted once. They expire after at most two years. Google keeps the detailed, per-visit data for the retention period set for this site, at most 14 months; the aggregated reports (totals, such as page views per day) are kept longer. This site shows no ads and has no advertising code. Google processes this data under the [Google Privacy Policy](https://policies.google.com/privacy); see also [how Google uses information from sites that use its services](https://policies.google.com/technologies/partner-sites). ## Cloudflare Web Analytics Cloudflare Web Analytics counts page views without cookies. It stores nothing on your device and does not identify or follow you across sites. It records the page address, the page that linked you here, your browser, operating system and device type, your country, and how fast the page loaded. See the [Cloudflare privacy policy](https://www.cloudflare.com/privacypolicy/). ## Opting out Both tools run as JavaScript: with JavaScript switched off, nothing is counted. To stop Google Analytics, block its scripts with a content blocker or install Google's [Google Analytics opt-out browser add-on](https://tools.google.com/dlpage/gaoptout). Blocking or deleting this site's cookies removes the Google Analytics ID, but visits are still counted, each one as a new visitor. ## Stored on your device - `theme` (local storage): light or dark, if you used the theme button. It is never sent anywhere. - The Google Analytics cookies above. ## Videos Every lesson is a YouTube video. The lesson pages show a preview image stored on this site. Nothing is loaded from YouTube until you press play; pointing at or focusing the play button only opens a connection to YouTube's servers in advance, so the video starts faster. The video then plays from youtube-nocookie.com, YouTube's privacy-enhanced mode, and YouTube's and Google's privacy terms apply to it. "Watch on YouTube" links open YouTube itself. ## Search The search page runs in your browser, using a search index downloaded from this site. A search started from the search box in the header or on the home page opens the search page with the words in its address (`/search/?q=…`), so Google Analytics records them as part of that address; words typed on the search page itself stay in your browser. The search API for agents (`/api/search`) answers on this site's server; the search service itself keeps no log of the queries, but the server's access logs (below) include the address of each search request. ## Server logs Like every web server, the server that hosts this site keeps standard access logs of page and search requests (IP address, time, the address requested and your browser). They are used only for security and troubleshooting, not for analytics, and they are not shared. ## Contact For questions about your data or this page, use the [contact form](https://forms.gle/jQSx5KoXvrVA1JCK7) to reach Roy Osherove. --- title: "The Art of Unit Testing & TDD Master Class in .NET" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/" tags: [] author: "Roy Osherove" description: "The Art of Unit Testing & TDD Master Class in .NET: 14 lessons, 9 h 6 min. A free video course by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # The Art of Unit Testing & TDD Master Class in .NET [Courses](https://courses.osherove.com/#courses) 14 lessons 9 h 6 min 5 sections [Start course](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/unit-testing-and-tdd-101/) [Watch on YouTube playlist](https://www.youtube.com/playlist?list=PLCQ11BGiNTic) ![](https://courses.osherove.com/img/yt/WWZR6vq6BvU.jpg) Recorded LIVE during five days of [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6 "Test-driven development (The Art of Unit Testing, 2nd ed., ch. 1)") master class with Roy Osherove. ## About this course Roy Osherove teaches [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") and [test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") in .NET, starting with [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)"), [test naming](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html "Naming standards for unit tests (osherove.com)") and the cycle of failing test, passing code and refactoring, practiced on the string calculator kata. The course then covers [hand-written fakes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec3 "A simple handwritten mock example (The Art of Unit Testing, 2nd ed., ch. 4)"), [mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_79 "The importance of differentiating between mocks and stubs (The Art of Unit Testing, 3rd ed., ch. 4)"), [isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99 "Defining isolation frameworks (The Art of Unit Testing, 3rd ed., ch. 5)") such as [Moq](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5 "Current isolation frameworks for .NET (The Art of Unit Testing, 2nd ed., ch. 5)"), [FakeItEasy](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html "FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition? (osherove.com)") and [Typemock Isolator](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html "Minimizing unit Test Fragility – 8 features in Typemock Isolator to help (osherove.com)"), and [reviews of real test code](https://osherove.com/videos/2011/2/6/how-to-do-test-reviews.html "How to do test reviews (osherove.com)") from [NerdDinner](https://osherove.com/blog/2009/3/20/test-review-1-nerddinner.html "Test Review #1 - NerdDinner (osherove.com)") and [Microsoft's Unity](https://osherove.com/blog/2009/3/23/test-review-3-unity.html "Test Review #3 – Unity (osherove.com)"). It ends with techniques for legacy code, such as [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") and static forwarding, and with talks on faking whole host systems such as Silverlight and SharePoint. ## Related reading - [Test Review Guidelines](https://www.artofunittesting.com/unit-testing-review-guidelines) · artofunittesting.com From the lesson [Test Review Practices](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-review-practices/): Roy's checklist for reviewing tests, grouped under readability, maintainability and trust, the pillars used in this lesson. - [Constrained and unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1) · The Art of Unit Testing, 2nd ed., ch. 6 From the lesson [Isolation Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/isolation-frameworks/): The 2nd edition's section on constrained and unconstrained frameworks, the proxy versus profiler split the lesson explains. - [Test Review #1 - NerdDinner](https://osherove.com/blog/2009/3/20/test-review-1-nerddinner.html) · osherove.com From the lesson [NerdDinner Test Review](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/nerddinner-test-review/): Roy's earlier published review of the same NerdDinner tests, for comparing notes with this class session. - [Code excavations, wishful invocations, perimeters and domain specific unit test frameworks](https://osherove.com/blog/2010/3/19/code-excavations-wishful-invocations-perimeters-and-domain-s.html) · osherove.com From the lesson [Code Excavations and Domain Specific Test Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/code-excavations-and-domain-specific-test-frameworks/): Roy's written write-up of this talk's ideas: code excavations, wishful invocations, perimeters and domain specific test frameworks. - [Mock Objects vs. "Inherit & Override"](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html) · osherove.com From the lesson [Using Extract & Override](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/using-extract-and-override/): Roy compares mock objects with subclassing and overriding a virtual method, the extract and override approach shown here. ## Curriculum Section 1 ### The Basics 2 lessons · 2 h 23 min This section covers what a unit test is, the readability, maintainability and trust that good tests need, and how to write and run NUnit tests in Visual Studio. Roy Osherove then shows the test-driven development cycle of a failing test, the simplest passing code and refactoring, first on a calculator class and then in the string calculator kata, which the audience does in pairs. 1. [Unit Testing And TDD 101 Duration 1:55:52](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/unit-testing-and-tdd-101/) Roy Osherove defines a unit test and the three properties of a good one, readability, maintainability and trust, and explains why unit testing efforts fail when any of them is missing. Writing NUnit tests in Visual Studio for a calculator class, he covers three-part test names, readable inputs, factory methods instead of setup methods, and Assert.Throws instead of the ExpectedException attribute. He also separates unit from integration tests, runs tests with TestDriven.NET, and adds features test first: a failing test, the simplest passing code, then refactoring. 2. [Test Driving a String Calculator Duration 27:29](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-driving-a-string-calculator/) Roy Osherove introduces code katas for practicing TDD and starts the string calculator kata, whose Add method returns the sum of the comma-separated numbers in a string. He writes one test at a time, starting with an empty string returning zero, and makes each pass in the simplest way, from always returning zero to int.Parse, finding a bug on the way. He runs the tests with NCover, saying coverage means little without test reviews, and sends the audience to do the kata in pairs. Section 2 ### Fakes, Mocks and Stubs 3 lessons · 1 h 26 min This section covers replacing dependencies in tests: redirecting a console application's output in memory, a hand-written fake logger behind an ILogger interface, and the difference between mocks and stubs. The last lesson compares proxy-based isolation frameworks such as Rhino Mocks, Moq and FakeItEasy with profiler-based ones such as Typemock Isolator, which can also fake static methods and future instances. 3. [Test Driving a Console Application Using String Calculator Duration 16:54](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-driving-a-console-application-using-string-calculator/) Roy Osherove test-drives a console application that uses the string calculator by calling its Main method in memory from a unit test, after making Program and Main public. He mentions compiler flags and the InternalsVisibleTo attribute for keeping members hidden, then redirects console output with Console.SetOut to a StringWriter over a StringBuilder and checks it with StringAssert. The aim is to connect the string calculator layer to the console layer with a couple of tests, and he moves the console replacement into a helper method. 4. [Introduction to Hand Written Fakes, Mocks and Stubs Duration 7:18](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/introduction-to-hand-written-fakes-mocks-and-stubs/) With a login manager whose save method must also call a logger written by another team, Roy Osherove introduces an ILogger interface so a hand-written fake logger can replace the real one. A fake the test asserts against is a mock object, one it does not assert against is a stub, and the same class can serve as either. He also explains that injecting the fake through a constructor, rather than a property, tells the user of the API the dependency is not optional. 5. [Isolation Frameworks Duration 1:01:27](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/isolation-frameworks/) Roy Osherove explains isolation frameworks, which create fakes at runtime, and divides the .NET ones into proxy-based frameworks such as Rhino Mocks, Moq and FakeItEasy and profiler-based ones such as Typemock Isolator, JustMock and Moles. Profiler-based frameworks rewrite the IL at runtime through the CLR profiler API, so they can fake static and private methods; proxy-based ones need interfaces or virtual methods. He compares their APIs on the same logger tests, from string-based NUnit Mocks to Rhino Mocks extension methods, and shows Isolator faking static methods and future instances. Section 3 ### Test Review Insights 3 lessons · 1 h 53 min Roy Osherove explains why to review tests and what to look for under readability, maintainability and trustworthiness, with examples of logic, magic numbers, multiple asserts and over-specified mocks in real tests. He then reviews the NerdDinner tests and goes through the audience's review of the tests of Microsoft's Unity project. 6. [Test Review Practices Duration 1:00:31](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-review-practices/) Roy Osherove explains that test reviews spread knowledge and that reviews starting from the tests are shorter because tests show the developer's intent, and names readability, maintainability and trustworthiness as the pillars of good tests. In tests from NerdDinner, ASP.NET MVC and other projects he points out logic, magic numbers, dynamically built expected values and several tests in one method. He also warns against over-specified mocks that should be stubs, allows at most one mock per test, and breaks production code by hand in reviews to see whether a test fails. 7. [NerdDinner Test Review Duration 27:17](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/nerddinner-test-review/) Roy Osherove reviews the NerdDinner tests, starting with a single test project that mixes unit and integration tests; he wants them separated into a safe green zone of tests that always pass. A failing HTML rendering test depends on the machine's locale, and he discusses test names, var, magic numbers such as 999, and mock helpers that are really stubs. Different naming conventions show him there was no test review process, and he objects to test dinners created in a hidden helper with a dynamic date. 8. [Unity Test Review Duration 25:37](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/unity-test-review/) After the audience reviewed the tests of Microsoft's Unity project, Roy Osherove goes through their findings, including a test with no assert and setup methods that hide the arrange part, which he replaces with factory methods. They discuss bug recreation tests, which belong in a clearly named class, a test that depends on release or debug build flags and is therefore an integration test, and a structure that does not separate unit from integration tests. He ends by writing an Assert.Throws-style helper for MSTest, which lacks one. Section 4 ### Legacy Code 3 lessons · 55 min This section shows ways to test code that was not written to be testable: extract and override on a login manager with static dependencies, and a static forwarder on a static ping manager class in BlogEngine.NET. The last lesson tests the same blog engine code with Typemock Isolator, faking static methods, a singleton and future instances of a class. 9. [Using Extract & Override Duration 21:33](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/using-extract-and-override/) Roy Osherove introduces extract and override, from the book Working Effectively with Legacy Code, on a login manager calling a static logger: the call moves into a protected virtual method with as little logic as possible, which a testable subclass overrides. He extends it to simulate a logger exception, check a static web service call and control the machine name rather than build the expected value dynamically. He also uses it to return fake objects, compares it with Moq's protected API, and discusses keeping extracted methods protected or public. 10. [Static Forwarding on a real legacy app Duration 13:44](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/static-forwarding-on-a-real-legacy-app/) In BlogEngine.NET, downloaded from CodePlex, Roy Osherove looks at the static Send method of a ping manager class, which finds links to other blogs in a new post and sends trackbacks or pingbacks. Since the class is static, extract and override cannot be used, so he creates a static forwarder: the static method calls a non-static copy on a new instance, whose dependencies become virtual methods. He advises having integration tests before such a risky refactoring and sets an exercise: test when trackbacks and pingbacks get sent. 11. [Testing Legacy Code with Typemock Isolator Deep Dive Duration 20:08](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/testing-legacy-code-with-typemock-isolator-deep-dive/) Roy Osherove tests the same blog engine code with Typemock Isolator, explaining why Visual Studio must be restarted for a profiler-based framework and what the Isolated attribute does. He fakes the static methods of the trackback class to verify that Send was called, then follows each failure, which he calls wishful invocation, faking a non-public static method, the blog settings singleton and all instances of a remote file class. The test passes without any debugging, and he asks the audience to get to the same point. Section 5 ### Bonus tracks on advanced patterns 3 lessons · 2 h 28 min Two talks show how to unit test code that runs inside a host system such as Silverlight or SharePoint by intercepting the system with CThru and faking its internals, the approach behind the SilverUnit framework. The other lesson uses extract and override with a test specific subclass to test-drive password validation logic separately from each rule. 12. [Code Excavations and Domain Specific Test Frameworks Duration 54:14](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/code-excavations-and-domain-specific-test-frameworks/) In a talk, Roy Osherove looks at code hosted inside a framework, such as a Silverlight control that cannot be created in a unit test, and at Microsoft's Silverlight test framework, which runs tests in the browser. He compares faking interaction points with an isolation framework, wrapping the system in role-based abstractions, and excavation, where wishful invocations reveal deep dependencies to fake. Using the open-source CThru framework, he disables Silverlight constructors and methods one dependency at a time, which led to SilverUnit, a domain specific test framework running tests in memory. 13. [Testing Complex Validation Knowledge using Extract & Override Duration 43:35](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/testing-complex-validation-knowledge-using-extract-and-override/) Roy Osherove explains how to test validation logic that combines many rules, using a password validator, by testing each rule separately from the logic that combines them. He introduces extract and override, also called the test specific subclass pattern, with a testable subclass that overrides the current time so a backup check does not have to wait seven days. He then writes a validator test first, with flags in a testable validator that set what each rule returns, and tests a single rule method directly using the InternalsVisibleTo attribute. 14. [Mocking On The Edge Duration 49:54](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/mocking-on-the-edge/) In a 400 level talk, Roy Osherove builds a domain specific isolation framework that stubs out a third-party system by default, using the Typemock Open AOP API, which hooks into the CLR profiler API. For SharePoint he fakes an SPSite title in one test, writes an interceptor that logs every method call, and uses CThru aspects in a custom test attribute to disable the SPSite constructor and skip SP global methods. He shows SilverUnit using the same approach for Silverlight, unlike Microsoft's browser-based test framework, and ends with a song. --- title: "Unit Testing And TDD 101" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/unit-testing-and-tdd-101.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/unit-testing-and-tdd-101/" tags: [] author: "Roy Osherove" description: "Lesson 1 of 14 in The Art of Unit Testing & TDD Master Class in .NET (The Basics), 1:55:52. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Unit Testing And TDD 101 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 3. The Basics Lesson 1 of 14 Duration: 1:55:52 [Watch on YouTube](https://www.youtube.com/watch?v=WWZR6vq6BvU) Roy Explains [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") and [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1 "Defining unit testing, step by step (The Art of Unit Testing, 2nd ed., ch. 1)") from scratrch, including how to setup the environment for flowing development. ## In this lesson Roy Osherove defines a [unit test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") and the three [properties of a good one](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_23 "What is a good unit test? (The Art of Unit Testing, 3rd ed., ch. 1)"), [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)"), [maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)") and [trust](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134 "How to know you trust a test (The Art of Unit Testing, 3rd ed., ch. 7)"), and explains why unit testing efforts fail when any of them is missing. Writing [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)") tests in Visual Studio for a calculator class, he covers [three-part test names](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html "Naming standards for unit tests (osherove.com)"), readable inputs, [factory methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "Trying the factory method route (The Art of Unit Testing, 3rd ed., ch. 2)") instead of [setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162 "Avoid setup methods (The Art of Unit Testing, 3rd ed., ch. 8)"), and [Assert.Throws](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6 "More NUnit attributes (The Art of Unit Testing, 2nd ed., ch. 2)") instead of the ExpectedException attribute. He also separates unit from [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)"), runs tests with TestDriven.NET, and adds features test first: a failing test, the [simplest passing code](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)"), then refactoring. ## Transcript 17,512 words [\[00:26\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=26s) To teach you. We have Roy Osherove who ordered the book [the art of unit testing](https://www.manning.com/books/the-art-of-unit-testing-third-edition "The Art of Unit Testing, Third Edition (The Art of Unit Testing, 3rd ed.)") which is really great. We have a couple of copies of the company if anyone want to read it but over to you. >> You just bought two copies for the whole company. Okay. >> Yeah. I I specifically asked for people to bring some laptops so that we might have later after after the early breakfast [\[00:58\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=58s) Some some workshops. I'd like to start first of all by moving this screen a little bit. How many people here have tried to write a [unit test](https://www.artofunittesting.com/definition-of-a-unit-test "Definition of a Unit Test (artofunittesting.com)")? Okay, how many people here have succeeded in working with unit tests? [\[01:31\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=91s) About half of the people who tried. How many people here have just heard of it? Okay. How many people here work with JavaScript or UI related stuff? >> Okay. And the rest what do you work on? >> Just .NET stuff. C#. >> Yeah. >> Yeah. Java >> desktop or web. >> Web. Okay. [\[02:03\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=123s) So this is about [test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6 "Test-driven development (The Art of Unit Testing, 2nd ed., ch. 1)"). But the day kind of looks like this or the the first half of the day. We're going to talk about unit testing as a separate activity from testdriven development cuz they are separate skills. Test-driven development is basically when you write those tests. So if you don't know how to write good tests, you can do test-driven development with really crappy tests as well, which can actually hurt your project. So we're going to learn how what it means to write a [good unit test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec2 "Properties of a good unit test (The Art of Unit Testing, 2nd ed., ch. 1)"), what a unit test actually means, [\[02:38\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=158s) And what are the properties of a good unit test. [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec3 "Writing readable tests (The Art of Unit Testing, 2nd ed., ch. 8)"), [maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec2 "Writing maintainable tests (The Art of Unit Testing, 2nd ed., ch. 8)"), and [trust](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134 "How to know you trust a test (The Art of Unit Testing, 3rd ed., ch. 7)"). So you actually trust the result of a test. But the nice thing about test-driven development as an activity is that even though it started as part of something called extreme programming, you can take this activity as it is and implement it wherever you want regardless of the methodology that your organization uses because TDD kind of like debugging. It's an is a personal activity. [\[03:10\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=190s) It's something that you can choose to do wherever you are. So it's always a choice. It's also a choice not to do it. Even if someone forces you to do it. So I've seen organizations where people have actually failed the company when people forced them to do TDD and they didn't want to. So I don't know if you know this but don't want to do something they easily don't do it even if someone tells them to do it. So >> they can fail their manager by by doing exactly what they were told. [\[03:42\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=222s) Right. Not a second more. Oh, it's 5:00. I have to go home now. I know it's not working the build, etc. All that stuff. So, it's always a choice. What we're going to do, we're going to talk about the choices that we make when we when people do test room development and why a lot of efforts when for people who do unit testing in TDD fail. But to understand that, let's try to define what a unit test is. This is the most basic definition. [\[04:12\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=252s) It's not a good definition, but it's good enough to start. A unit test is a test of a small functional piece of code. A better definition is that it's a piece of code that invokes another piece of code. But that other piece of code will only usually have logic inside it. So if we have a method called is login okay and returns a boolean it will probably have logic inside it such as an if or switch or loops anything like that. [\[04:42\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=282s) We wouldn't want to write tests for something that doesn't have logic at all. So for properties getter setters that don't have logic probably wouldn't want to write a direct unit test for those. So if I give you this method description and I I don't even tell you what the body of the method is, but we assume that it's a regular method. How many tests do you think we can write for such a method? What's the minimum amount of unit tests that we can have for this method? [\[05:17\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=317s) Any thoughts? By the way, if I didn't if I didn't make myself clear, is this is going to be more of a discussion than just a a lecture. So, what's the minimum amount? Anyone? >> Two. >> Two. Cuz it's a boolean returns true or false. It's a good start. Anyone else have a different number? >> Four. >> Four. Why? Because you have two parameters. So, you could probably combine the par parameters in four different ways. >> Okay. So if you combine the parameters in four different ways regardless of the two that we already had that's six or did you mean four including what she said? [\[05:58\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=358s) >> So what would you send in for these parameters? >> Either a string null or an empty string. >> Okay. A regular string a null or an empty string. Okay. So that's three for this. And then >> same for that. >> The same for that. >> Okay. So that's six. >> Plus the other two. So that's eight. >> Lots more. >> Well, I'm not saying what's the maximum is. What's the minimum? >> What is the minimum of that? >> No, but still I mean valid username, valid password, valid combination, username, password. [\[06:34\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=394s) >> Mhm. >> Exceptions. >> Exceptions. Okay. So let's try to get consensus. Who thinks it's the minimum is two? Raise your hand. Who thinks the minimum is three, four, 5, 6, 7, 8? More than eight. And the rest of you just didn't raise their hands. So, good morning. Please get a coffee. [\[07:04\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=424s) Important to listen. Let's let's do the absolute [simplest thing](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)"). Let's say it's it's three somewhere between two and four. Okay, we have to have at least three unit tests for this thing cuz we want to check the two boolean values and at least a parameter or something, maybe an exception. So, how many methods that contain logic do you have in your project today? [\[07:35\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=455s) More than 100. Raise your hand if it's more than more than 500. >> Yeah. >> More than a thousand. >> Okay. >> How many unit tests should your project have at the minimum, do you think? Simple math. More than 500 tests, more than a thousand, more than 2,000. Okay. Who has more than a thousand tests in their projects today? >> Almost. [\[08:06\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=486s) He's like almost pregnant. >> Yeah, exactly. >> It's either or. >> Yeah, if you count in the exception test acceptation >> expectation. So that means that you have like 500 or 400 methods with logic project. >> So it's pretty small project. >> Yeah, that project is pretty small. >> Okay, so that's one project. How many projects do you guys have? [\[08:37\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=517s) >> Five a piece. Five for each person. Five projects for each person. >> Yeah, about. But we combine. >> Okay. So, how many total projects does this company have, do you think? >> 30 maybe. >> 30. Okay. >> One out of 30. Pretty good. I >> think more than 30 I think. >> One out of more than 30. Pretty good. >> Good project. >> Why do you think that is? >> It doesn't really matter. It's just a question. >> So, why do you think that is? >> The time issue. I think the customer doesn't want to pay for the service. [\[09:07\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=547s) >> The customer doesn't want to pay. So, so we don't want to do it because it takes time. >> The customer, we we don't have the time to do it >> because we let the customer choose whether we want to write unit tests or not. It's like asking the customer, the car costs $20,000 with wheels. What's he going to ask next? Okay, how much is without wheels? Okay, it's like the same question. But, you know, that's a philosophical question. Forget about that. [\[09:38\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=578s) Let's say that we most projects do have enough time at least to try some of these things. To understand that, we have to understand what people mean when they say that unit testing is actually good for you. Actually try to to see if that that's true. is when when people like me come to a company, they say, "Look, unit testing will make your lives better, [\[10:08\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=608s) Especially if you do it in TDD." Because when you have 2,000 unit tests, it's easier to find bugs in your code. Who thinks that's true? Okay, who thinks that's not necessarily true, though? I think so. Let me give you an example. What if your tests have bugs? Is it easier to find bugs then or is it much worse? Because you do not test your tests. So the if you have a bug in your test, the last place you look for is in the test. [\[10:42\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=642s) So it actually takes longer to find bugs if your tests are wrong. So that's not necessarily true. And how do you know if your tests have bugs? You are you going to write a test for your test? And how do you know the test for your test that doesn't have bugs? So it's a very recursive problem. So testdriven development helps with that because with TDD, maybe you've heard of this. You start with a failing test and then you make the test pass. And by seeing the test fail first and then pass. [\[11:15\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=675s) You actually get [to test the test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "Testing the test (The Art of Unit Testing, 3rd ed., ch. 2)") manually, but it's still a test. So you know that it's it's it's failing when it should and it's passing when it should. So, it's one of the only ways I know to actually make sure your tests don't have bugs. It's easier to maintain your code when you have 2,000 unit tests. Who thinks that's true? Are you afraid to raise your hand now? Okay. Who thinks that's not true? Why? >> Because if you have to change something, you have to do it and [\[11:52\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=712s) Do the process. you have to change something, you actually have more code to maintain. So that's not necessarily true. So imagine 2,000 unit tests on a on a code base. It could be easily take another half, another 50% of the codebase added. Imagine that you have 20 tests creating an instance of a class and now you've gone ahead and added a parameter to the constructor of the class. So now you have 20 tests that don't compile. You have to go through each one and actually change them. [\[12:23\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=743s) And that sucks because you don't want to do that. That takes too much time. So when you have enough tests, they actually begin to slow down your project instead of helping. That's one of the first projects I ever did with unit test had that problem. So after about 6 months, we actually started removing some of the test that we worked so hard to create. So this is absolutely not true by default. It's only easier to maintain if we learn some practices that make the tests more maintainable [\[12:55\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=775s) Such as refactoring in the tests themselves. So this could be true but this is one of the biggest problems with unit testing and TDD is that organizations try to implement these things and they get into the maintenance problem and it's it's if you do it enough you it feels like walking in concrete. you want to fix something in the code and you're just afraid of breaking so many tests for the wrong reason that you don't want to do it. So you start hating the tests [\[13:25\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=805s) Instead of them helping you. You start hating them and that's usually not a good idea. So we're going to learn what it means to be maintainable. It's easier to understand your code when you have 2,000 unit tests. That might need more explanation. When people say talk about unit testing and TDD, they also refer to it as documentation for your code. Live executable documentation. So you should theoretically be able to get a new person in your team, tell them look at this at the test for this class. [\[13:56\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=836s) We need to fix a bug and they should just look at the test and understand magically everything that's happening and be able to fix it. But in reality, the tests are so poorly readable with really bad names that no one can really understand what's going on. So names of tests can be as bad as names of methods. If you've ever come across methods named do this, do it. Then we also have tests like that. Test one, test two, test two. [\[14:29\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=869s) Two, etc. So it's pretty horrible the state of testing because people don't pay attention to the readability of the tests. So this could be true but by default it's not true. Only when all these three things are true do actually unit testing and TDD help you. If even one of them is false then it breaks down the other two and unit testing begins to be a burden instead of helping. So you can maybe start seeing why so many organizations are actually trying to implement unit testing in TDD and failing [\[15:01\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=901s) Maybe failing after a few months maybe failing in the beginning because they try to either do too many things at the same time or they don't understand these problems so they don't learn how to make things more maintainable more readable and they don't trust their tests. An example of mistrust is when you have a bunch of tests and you run them and you get a green light, everyone everything passes and you still get the urge to debug your code just to make sure that means you don't trust your tests. Okay, if you are in that position, something was wrong [\[15:36\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=936s) Because the test maybe you've experienced the test that are false positives or anything like that. TDD helps with that feeling to make sure that you actually trust the things that you run so that when they pass you actually good about yourself. So get getting back to the question of why do people not have enough tests? Well, part of it is because they get slowed down by these problems and part of it is because [\[16:06\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=966s) It takes a lot of time to to have enough tests in your project. because people don't use usually frameworks to do the their test. They create their own frameworks. They create their own forms. And I usually tell people that everyone I I know has already done unit testing cuz I don't know a single developer that does not check their code before giving it to someone else. Everyone does it. The only difference is is it automated? Is it structure? Can anyone else test the code that you just did or are you the only one? [\[16:37\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=997s) Cuz when I started before doing unit testing with automated tests, I used to create forms, you know, with buttons. Text one, text two, button one, button two. It looked like a Picasso painting. Only I knew the exact order of pushing all these things. And at some point, magically, I knew that something was working, but no one else on my team was able to use that form. And of course, I didn't remember to do it two months later. So most people do test their code but they don't do it in a repeatable way. [\[17:07\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1027s) They don't do it on all their code because it takes time to reinvent the wheel every time and create those forms and consoles. So they they just choose the things that scare them the most and they test those. But there is another problem with why people don't with another reason why people don't add a lot of tests is because when you write the code you're not objective about whether it's working or not. I think we all know this. [\[17:38\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1058s) If you write a code you're when you test it your objective is to prove it works. Okay? So you're expecting it not to fail. So you're only doing the simplest thing to prove to yourself that you did a good job. That's a very human thing. That's why sometimes we say that QA is good to be a separate part because it's a different person who's not who's more objective about your code. So they're actually looking for your code to fail, which is a better thing to do. [\[18:09\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1089s) But with TDD, we have several practices that make sure that we don't we don't become too subjective. We become a bit more objective. So we try to see our code fail instead of pass. And when we do that, we get more tests. We actually try to prove that something doesn't work. And then we get better [code coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)") and all that stuff. But that's not easy to do. We need a practice to learn how to do that. But the the most fundamental shift when people start doing testing in automated way is framework. [\[18:46\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1126s) So there are a bunch of frameworks for doing unit testing in practically every language you can think of. Most of them are open source and free. Some of them are not free. I think maybe just one or two in .NET world. The first one started with Smalltalk. Anyone here ever tried Smalltalk by the way? Okay. So there is one when I started doing unit testing I was working in VB5 and VB6. So I started with a framework called VBUnit about 10 years ago. [\[19:17\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1157s) I had no idea what I was doing. It was pretty horrible experience but the I remember the things I remember from then still apply today in terms of how do I write tests. What I'm trying to say is that all these frameworks have a standard test architecture. So if you've written tests with one of these frameworks before and you know a different language, writing tests in that different language should be seamless, should be very easy because the idea of how to write the test, how to structure them, how to execute [\[19:49\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1189s) Is about the same in all these frameworks. So they're collectively called the [xUnit frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)") and everything that represents X is the name of the language at the beginning. So SUnit etc. Today we're going to cover [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)") which is an open- source free framework for .NET. However these are just examples. You can apply a lot of the lessons here to any programming language that you use either Java or JavaScript. [\[20:22\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1222s) There is for example it's not written here but for JavaScript there are several unit test frameworks. The a really big one used was a cube cube unit though it's considered a bit old these days. The one that's that everyone is talking about in JavaScript these days is called Jasmine. So if we if we get time to do workshops today the JavaScript developers I will ask you to try to use Jasmine for your for your workshop. [\[20:53\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1253s) Okay. But most of the demos will be innet. What do all these frameworks provide? What do they give us? Well, they give us a structured way to write the tests. Usually as methods inside classes and those methods will have attributes on them and those classes will have attributes on them. They give us a structured way to run the tests. So those attributes will be used by two types of runners either command line runner or a UI runner. And all these runners what they do is they look at the compiled code that you that you created if it's compiled and they look for these attributes that mark a class that contains tests and when they find those they execute all the tests in that class with se several simple rules in between [\[21:40\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1300s) And they allow you to also review the results. So if a test failed it will tell you the line number where things failed, what actually failed. Maybe you expected one thing but you got another. So you should be able to get the feedback on whether something works or doesn't work very quickly and go to the code that doesn't work pretty quickly. And all these are done in the same way across frameworks and the point is so that so that you can share this knowledge. If I wrote a unit test then anyone else in my team can run the unit test. [\[22:15\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1335s) Anyone else can can see the feedback because the feedback is the same. It's same output type. So anyone can take action based on it. So it's no longer me creating reinventing the wheel. Before we do that, here is how you in you create a class containing tests with net. By the way, what do you guys use? MSTest or NUnit these days? >> NUnit. NUnit. Okay. So, NUnit is definitely the preferable framework to MSTest because it has more features and it's [\[22:51\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1371s) It's more stable. It's also faster than MSTest. It's also free and open source. So, you can actually extend it, see the code, understand how it was written, more extensible. To create a class that contains test, you just create a regular class in your code, hopefully in a separate test project. You add a reference to nunit.framework framework DL and from there you import an attribute called test fixture and test fixture is a name inherited from early days of JUnit because NUnit was built on the idea of JUnit from Java but Java was first in unit testing That was bit of a late second. [\[23:32\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1412s) I don't like this name for me. It took a while to understand what fixture fixture means. So I just call it test class in my head. This is a test class. And that's one thing that MSTest, right the name of the attribute is more readable. But that's basically the only problem that I see. So we put a test fixture otherwise the test won't get recognized. Then we create a public void method in our class. Every method that is public and void, doesn't take arguments and has this attribute on it [\[24:08\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1448s) Will be executed automatically by the [test runner](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_37 "The library, the assert, the runner, and the reporter (The Art of Unit Testing, 3rd ed., ch. 2)"). This is by the way an example of a really bad name for a test. So here's an example of the badly named test and what a test might look like. So every test will usually have three parts. So they're collectively called the arrange, act, and assert or the AAA pattern. [\[24:39\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1479s) The arrange is the part where you arrange things to be tested on. You might create an instance of this, create an instance of that, set up multiple settings on your application model, create them in memory. The act part is actually acting on that object model. So invoking something or changing something and the assert part is the the part that's the most important is the part that decides whether the test failed or passed. [\[25:10\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1510s) This is a class called assert part of the nunit.framework DLL. That's the class you're going to use most of the time. It has a lot of methods with a lot of overloads for checking various things. The assert are equal are one of the most used methods in there. The first parameter is the expected value. The second parameter is the actual value. A lot of people get those mixed up. Nothing will happen if you get it mixed up except that the messages that you get from the framework will look really weird. [\[25:43\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1543s) Like in here, it might say, "I expected one, but it was three." You're going to look at the message and say, "No, but it was supposed to be three." So if you got these parameters wrong, you're going to get a lot of confusion. The last part of the most of the assert messages the methods is the message that will be sent if the test fails. You should never ever use this parameter. [\[26:14\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1574s) And the reason is that instead of this the name of the test should reflect what's supposed to happen. If the name of the test is good enough, you won't need to write this message. Okay? So, this and the [test name](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_168 "Naming unit tests (The Art of Unit Testing, 3rd ed., ch. 9)") are synonymous. And usually the test name is more important because when you have 2,000 tests and 10 of them fail, the first thing that you see is the name of the test. The messages are harder to read. The name of the test will contain most of the information that you that you can convey. [\[26:48\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1608s) So, we're just going to do a short demo and in that short demo, we're going to write our first unit test for a real project. I'm going to create a new project here. Actually I'm going to create a new solution because usually when we talking about projects and tests we will have separate tests in a separate project. [\[27:21\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1641s) So let's call it we're not doing test driven development yet. I'm just showing how to write unit test. But for now, actually going to create an existing product. It's going to be a class library just for demo purposes. product.logic. How's that? And I'm also going to show you how I use the environment in Visual Studio to change things. [\[27:55\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1675s) How many people here use ReSharper in Visual Studio? Okay. How many people here really know ReSharper? It's an interesting question. So I'll I'll show you how I try to use it and I would recommend learning all the shortcuts so that you can be much more productive when you write code. So let's create a class. I'm just going to rename it to my calculator. [\[28:28\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1708s) So it's a very complicated class as you can guess. public void add int a int b and of course it's an int. Sorry. Return a + b. That's not it. Not used to the >> alt good, right? >> I think has a Swedish keyboard there. >> So where is it? It should be it should be there. [\[28:59\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1739s) Test. Well, there it is. Okay. And if we have the just such a simple method, by the way, ReSharper tells me all this stuff is not used. I'm just going to alt enter to get rid of this. No need to have mess in my projects. To write the test for this, I'm going to create a new project. It's not going to be a test project because that's the MSTest version of this. [\[29:30\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1770s) We don't want that because it it creates a lot of extra stuff that we don't need. So, we're just going to create a regular class library. What should be the name of the test project? Usually, it's the name of the project that you want to tests or unit tests. So my product logic unit tests [\[30:01\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1801s) And the reason I'm saying unit test and not just the word tests is because I separate the idea of a unit test for from anything else. For example, an [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec3 "Integration tests (The Art of Unit Testing, 2nd ed., ch. 1)"). We'll talk about these differences soon, but for now you should know that you you probably have two types of test projects for each project. integration test projects and unit test projects and they should be separate for a lot of good reasons and one of them is being able to trust the results. So now if I want to test my calculator [\[30:34\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1834s) And I want to prove that this method works what do I name the class that contains the tests? My convention is the name of the class that you're testing if you're testing just a class tests. So my calculator tests and of course it needs a test fixture attribute. We don't have nunit here. So what I'm going to do I'm going to use NuGet. Who heard of this NuGet? [\[31:07\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1867s) For those of you who don't know what it is, it's a plugin for Visual Studio that allows you to install things dynamically from the web and add the references to the project. If you if you ever done Ruby, it's kind of like Ruby gems, only for .NET. So I can go to tools, library, package manager. Awesome name by the way, package manager console. It's here at the bottom and I can just say install package and NUnit. [\[31:39\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1899s) I can also have a UI to see all the packages and explore. This is just a much faster way to do it. So what what it's going to do now is it's going to go out to the web, look for the package, download it. Hopefully it will find that package. Download the package. Add each reference. And the interesting is that it by default adds different weird references to it that we don't actually need. Sorry. First of all, one of the basic things that happen is that you add it to the wrong project. [\[32:15\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1935s) By default, it's not set up to test projects. So you can see my product logic just got a bunch of new references. So I'm just going to delete them. I'm going to tell the package manager to be a bit smarter and do the same thing. Okay. So now here are the references that we have. [\[32:45\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1965s) We only need one of these. So the first one is the nunit framework. This is the important one. This is the one we're going to use. NUnit mocks is an internal assembly that was used to test nunit itself. Okay. It's not a [mocking framework](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99 "Defining isolation frameworks (The Art of Unit Testing, 3rd ed., ch. 5)") that should be used in a public production hub because it doesn't have all the features of today's frameworks and it's discouraged from using. So we actually going to remove this in a second. [\[33:18\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=1998s) The third one is called PNUnit and it's NUnit with parallel test support. We don't care about this yet. This is a more advanced scenario. So we don't want we don't need this. We just need the first one. I'm just going to delete these two. Okay. So now that I have the references, I'm going to use the test fixture. And if you haven't seen what I just did, I don't have a using yet. So, and so the test fixture word doesn't get recognized. [\[33:49\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2029s) So, I can use a special intellisense setting from ReSharper this in this case it's control alt space to add to get a list of things that I have a reference but not a using to. So, test fixture you might want to write this down if you want things to you want to know this later. So, test fixture and I also get the using for free. Next thing I'm going to do is I'm going to write my first test. So, how am I going to write this test? Well, it's going to be real a really simple one. [\[34:22\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2062s) We're going to prove that when you add two numbers, it sums those numbers up. Now, this is not usually what I would write a unit test for. And the reason is because there is no logic here. There is only a mathematical formula. We don't test mathematical formulas. We only test logic. But for the for demo purposes, it's okay because it's very very simple. Test [\[34:54\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2094s) Public void. What should be the name of the test? >> Some one sum one and three. Any other suggestions? >> That was a good suggestion. Although it's missing a few things. >> Maybe something that was expected. >> Was expected. >> Yeah. So what do you expect? >> Three. >> Three. Okay. >> Or you expect a sum. >> You expect a sum. But he said some. So here's the way I structure the name of the test. [\[35:24\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2124s) This will help you if you've never written test before. The way I think about what test should convey. Three parts of knowledge. The thing that you're testing or the unit. It could be a method. It could be multiple methods. it could be multiple classes. So it's not a unit in terms of amount of code. It's a [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)"). It's a scenario in the system. In this case, the whole scenario is contained in one method calling add. So add is the thing that I'm testing. Then I'm going to put an underscore so that it's easier for the reader of the test to understand to separate these parts. [\[35:59\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2159s) Add followed by the scenario. So I'm testing add by doing something with it. So add given two numbers. I could say given one and two, given two and three, whatever, but that's an implementation detail. I want it to feel like a requirement. So if you call add with two positive numbers, it sums them up. Might be a requirement or two numbers. Doesn't have to be positive. So it's it's the explanation of the implementation, not the implementation. [\[36:33\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2193s) So add with two numbers and then the third part is the expected behavior sums them up. So if I know how to read these three parts, I can turn it into an English sentence. Calling add with two numbers sums them up. I can also say maybe something like this returns the sum. It's also another way. There are many ways to name this but the three parts should remain even if you don't have the underscores. Even if you've thought about doing [BDD](https://osherove.com/blog/2008/10/4/bdd-behavior-vs-spec-frameworks.html "BDD: Behavior vs. Spec Frameworks (osherove.com)"), if you've ever heard of this, BDD also contains the three these three parts of knowledge. [\[37:08\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2228s) They just exist in different places. Okay? If you only have two of these parts or just one, the reader of the test is not going to understand some of the things. So, a lot of tests might look like this with the name add two numbers. So, the reader will be reading this and saying add two numbers. Okay. What's supposed to happen? So now they have to read your test to understand it. And if it's a good test name, you don't have to read the code for the test to understand the requirements. Sometimes it might look like this. [\[37:40\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2260s) Add returns the sum. Okay, when does it returns a sum? What should I send in? What's what's the point? Okay, so the scenario is important. And of course, sometimes it's this two numbers returns a sum. Okay, but what's being tested? And the reason it's important is because that sometimes in a test we will have multiple invocations of methods which one is the important one which one is the meaningful one for our purposes. So it should we so it's guide it's like a guide map telling us what what happens [\[38:16\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2296s) And you can see that ReSharper doesn't like my naming convention but that's not a new thing. So, I'm just going to shut him up by Alt Enter. Inspection options. Get a hint. That's much better. Now, the icon that you see on the left is from a product called Test Lint, which is a free product, and it's kind of like a [test review](https://osherove.com/videos/2011/2/6/how-to-do-test-reviews.html "How to do test reviews (osherove.com)"). So, it will tell you if you have problems in your test. So, what it says right now, if I click on it, [\[38:47\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2327s) No asserts. Okay. And no asserts. Sometimes you forget to write in a ser especially when you're just learning. So that might help. >> What was it called? >> Test Lint. Yeah, it's part of a commercial product, but this part is free. And we might talk about these things later. Right now, it's just installed on my system. So you might see this icon. I wanted you to know what it is. We're not going to talk about it anymore, though, because the whole point is that you don't need the splint hopefully after these four hours. [\[39:19\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2359s) Okay. Now another of a few more important things about the name. If the name is good enough then it will help you when you write the test. Okay. So sometimes especially when you're learning you're getting so caught up and deep inside the guts of the system of how to do this and make use [mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") and do this and do this framework that you forget what it is you were trying to do. That's when you actually look back up in the name of the test and say okay so this is what the assert should be should do. [\[39:54\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2394s) So the last part should tell you how the assert should look like. The middle part should tell you what the act should look like. Okay. Or maybe the middle part also tell you about the arrange part. What is the scenario? So it's worth it to spend a good amount of time on the name. Okay. I I've I've had times where I just sat there and thought about the name, especially if I was doing pairing for 10 minutes, sometimes [\[40:24\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2424s) 5, 10, 15 minutes just considering what the name is. What it means if you cannot write a good name, sometimes it means that you don't know how to test something. Sometimes it means that you're not sure what it is you're trying to test. So coming up with the name is basically the coming up with the design of the test in your head. When you can express the design in words, then you can actually start writing the test. So the name is one of the most important things. If you start out with a really bad name and you end up with a you might end up with a really crappy test because you don't have any guiding light about where you're trying to get to. [\[41:01\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2461s) But right now it's a really simple test. Let's create the instance of the calculator. My calculator I don't have a reference to that project. So ReSharper is smart enough to tell me, hey, you want to add a reference and use that. Yes. So my calculator C equals new my calculator. That's the arrange part. And now I'm actually creating an empty line so that the arrange and the add part are separate. I think it's more readable that way. [\[41:33\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2493s) C.add. >> Well, it takes two ins. >> Yeah, >> it won't compile. >> But I know it's meant to be fake. >> Yeah, but failing is not the same as non-compiling. Failing is that I run it and I see it fail. Okay. [\[42:04\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2524s) And we're not doing TDD yet anyway. Good try. What should I send in? One and one. Why is this a problem? Okay, so let's consider readability again. Okay, imagine that the reader of your test is a serial killer who knows where you live. >> It will give you some motivation to change. [\[42:35\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2555s) So imagine this serial killer looking at your test and saying, "hm, very nice name. I like the way they write the name and see add one and one. Hm, this must be important because they're sending in the same number twice." So it looks like a bit like magic. I wonder what it means. I shall go to their house and ask them. Okay, you don't want that. So you want things to be obvious. So sending in the same variable twice as inputs for a test is usually not a good idea unless that's specifically your scenario. [\[43:08\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2588s) Okay? For example, if this was a divide method or subtract, the order of the parameters would matter a lot. And if they're the same, sometimes you'd get a false positive because it would equal zero no matter what the order is if it's subtract subtract. You don't want that. You want to be able to have variability in the inputs. So, what should I send in? >> One and two. >> One and two. Other suggestions? >> One and five. >> One and five. [\[43:38\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2618s) Oh, that's much better. Do I hear seven? >> One and zero. Interesting. One and zero. Well, I have a problem with zero. I have a problem with five. Two is much better for me. Notice how much time I invest in getting a good input because readability is much more important in tests than it is in code because you're going to have much more tests for the same piece of code. And you need these to be executable documentation. [\[44:11\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2651s) So one and two is much better than one and five. Why? Because if the serial killer comes in and says, "So you're sending in one and five. Why five? What's so important about five? I shall go to their house again and ask them. But one and two, I can see the pattern. Oh, just two numbers, consecutive numbers. One and zero, oh, it's going the the other direction. And zero usually has special meaning in inputs. So don't use zero if you don't have to. [\[44:42\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2682s) One and two are good because they're the first simple numbers right after zero and they're consecutive. So your brain is designed to see patterns. So one and two is better. Then again, I mean, >> if we're going this way for readability, we shouldn't do it this way at all. We shouldn't take care variables with a name. >> We could we could >> tell them what the meaning of them is. >> That's true. However, if you have this as a consistent way of writing tests, it becomes just like you have loops with I and J. [\[45:16\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2716s) Everyone knows what I and J means, right? You don't have to give them a good name usually in loops. So, it's the same thing. If you always have one and two or you have strings that say some name instead of Henry. >> Yeah, but you write like the one you like some positive number or whichever. >> So you can when do I use a variable name? When I absolutely have no good inputs that don't feel magical. That's when I would give them a good name like some positive number. And then I can actually do this some [\[45:47\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2747s) Positive. Okay. But usually one and two is just good enough. I've never had problems with one and two. >> And it seems also when I was thinking one and zero like one aspect of the method that's good. >> But when you read tests, one and two is just more readable. It's just my experience. So if you if you read enough tests, you're going to see one and two just becomes second nature. Okay. And this is now now we're being practical cuz we take this all the way to chaos like variable names for everything like expected and all that stuff. [\[46:20\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2780s) And then becomes unreadable again. >> Yeah. But isn't that a bit bit dangerous because I mean there are scenarios where it's actually important that it is specifically one and two pass by ordering a list >> and then I would give them a good name that says an int that is below two for example that I would specifically state that the value is important. If the value is not important I give default values. These are default values. So I use because these are used much more then I would use these for the default value and I would use variable names when it's important when the values are important. [\[47:01\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2821s) So one and two. So we have another line in our test. Let's make sure that we have a value. So extract variable int result separate with another line. And the last part is the assert. assert are equal. We can see all these overloads. The first one is the expected. What should I write down? >> Three. >> Three. Why not write down 1 + 2? >> Cuz you're expecting three. >> Yeah, it's the same thing. [\[47:33\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2853s) >> What's the problem? >> I have logic. >> The serial killer will come to your house. >> The serial killer will say one. No, I didn't understand it. I'm expecting three. What's the problem? >> Readability. >> Readability. Seems pretty readable. It's just one and two. >> It's not clear enough. >> You're you're you're not testing. >> Well, here's the result. This is what it look like. [\[48:04\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2884s) So, big problem here is there are two problems. First, I have logic here. So I could actually have a [bug in the test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11 "How can we know we don’t have bugs in our tests? (The Art of Unit Testing, 3rd ed., ch. 11)"). I don't want to have any logic in a test. So that's the first reason. The second reason is that if you're creating the thing that you're expecting on dynamically, which I am one and two instead of just using three, then most likely I'm repeating the same logic from production code. So if production code has a bug and I'm repeating the bug in my test, my test will pass. [\[48:35\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2915s) I will never know that I have a bug. Okay? So it's usually a bad idea to dynamically create the expected value. By the way, Test Lint will tell me this says logic in test in this case. So three is much better. When we talk about reusing, maybe I needed one and one in multiple places in my test. I would still probably use one and one in multiple places because here the readability is more important than than the maintainability of the test. [\[49:11\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2951s) If you can't read it, it doesn't really matter. You can maintain it or not. You won't be able to maintain it if you can't read it. So now that I have these tests, how do I run them? So I can use the default NUnit runner, but no one uses that anymore inside Visual Studio. People use the command line runner in [automated builds](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec1 "Automated builds running automated tests (The Art of Unit Testing, 2nd ed., ch. 7)") but for us there are several ways. First we have ReSharper install. So you can see these green icons. So I can run this test like this. [\[49:43\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=2983s) It will compile my code and I can see the results Now, I'm not sure what why it's taking so much time, but now that we have the results, you can see a green bar. When people say red green refactor, they mean that green bar. Personally, I don't use the ReSharper test runner. It's just my preference. Lately, they fix all the bugs that I had a problem with ReSharper, so I would have no problem using it on a real project. [\[50:18\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3018s) But I usually choose a different runner. So, you can choose whatever you need. So the runner that I use is called TestDriven.NET. It's free for personal use. It costs money if it's commercial for a commercial project. But it has at least one advantage over ReSharper test runner which I'm going to show in a second. First of all, how do I use test driven? I can right click on a test and I see the rocket icon. That's how I run it. [\[50:48\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3048s) And based on where I click, it's going to run the test in that in that scope. So if I right click on the class, it will run all the tests in a class. If I right click on a project or in a solution, it will run all the tests in that solution. So usually what I do is I run all the tests in this project and the output is not visual. It's in the console. One passed, zero failed. Sorry, the name of the tool TestDriven.NET. [\[51:20\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3080s) That's also also the URL of the site. It's really really fast. Jamie Cansdale is a used to be an MVP for Microsoft. And he's a really smart guy. So he made this work for any version of Visual Studio, even the express version of Visual Studio, which doesn't support plugins. Okay. So, he made a plugin that loads in Express which doesn't support plugins. [\[51:51\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3111s) So then Microsoft legal approached him and said, "You're a bad guy. We hate you. Please stop." They took his MVP away. And but he's still working on these things. You know, I think that he cuz they didn't like that he allowed people to do unit test. So, obviously that's very understandable. So anyway, we were trying to run this test. How do I use test driven in my TDD process? [\[52:22\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3142s) First of all, I don't like to use the mouse too much. So I the first thing I do when I install a new IDE on my machine is to set a shortcut to rerun the test in my project. So the way you do it in Visual Studio is tools, options, keyboard. And this here, this is a magical place. You can find all the actions in Visual Studio that you can ever think of. And if they already have a shortcut, you can see that shortcut. So, if you've ever wondered how to [\[52:53\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3173s) Close a tool window, this is the shortcut for that. Okay. But for me, I'm just going to look for rerun tests. And there's one shortcut from testdriven looking like this. Going to press alt R cuz that's the one I like. U, it will tell me that alt R is currently taken by a very, very important shortcut in Visual Studio, image.ctangle [\[53:24\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3204s) Tool in the Visual C image editor. I'm going to take a risk and assign it to me. Once I do that, I can change my production code. For example, no matter where I am, if I press Alt R, it will run the test. I don't have to move to my test to run them. And I get a very quick feedback without needing to do a lot of work. So, if I do this, a plus one error, hold R, no need to even save because it saves and compiles for you. [\[53:56\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3236s) I can see the results on the bottom really quickly. Another nice thing about it is that if you see results that look like this. So that's the line number and the column number, you can double click and you'll get directly to that line. You can see this >> was all our context based >> context or was it >> the context is global so it will work everywhere. >> Okay. You can choose to only have it work in specific context, but I don't touch that stuff. [\[54:28\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3268s) Just say global. Don't care. It's called brute force engineering. So this is expected three, but was four. And you'll notice I didn't have to write a message on the assert to get this. This is built in to all the frameworks. So if the test name is good enough and the messages are good enough, all I need to do is to look at the name of the test say add two numbers return failed. that will usually tell me that I might not even need to look at the test itself, but I can go directly to the code. [\[55:05\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3305s) Questions so far, >> how how do you read the test? >> How do I read it? >> Yeah, I start reading the asset code first. >> Yeah. >> And then the logic. >> if you if you didn't write the test, I would suggest reading it from the bottom up. So you would start from the bottom and say okay this is the assert. The line just before it is usually the act part and the top line is the arrange. But I would start with the name and then I would start with the assert because the name is the most important part. Other questions? [\[55:37\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3337s) Okay. So you see it's pretty simple to write a test but it's not maintainable. For example, I'm instantiating my calculator directly inside the test. That's usually not a good idea. I would refactor this. And we're going to see exactly how we're going to do this. But I only do this when I have two or more tests passing that use the constructor. And the reason is when I do TDD, for example, the point is to drive new development. [\[56:09\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3369s) I don't refactor my tests until at least I have two of them that need the same thing. Otherwise, I just leave it alone because there's only one usage of the constructor. So no need for a problem later. Let's see some more attributes that built are built into NUnit. The first one is called setup. And setup is allows you to create a method my setup. [\[56:43\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3403s) And in my setup it gets executed once before each test in your project. So the setup if I run this you can see that setup gets executed first and then any tests. So if I had two tests setup would be executed twice. Okay once before each test in my file. This is important because this is a good place to initialize things or maybe not. We'll see in a second. So what I can do to avoid this maintainability problem is to just delete the whole thing, [\[57:18\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3438s) Declare it at the class level and here sorry I would say C equals equals new my calculator. So now my test looks like this. If I run the tests, [\[57:51\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3471s) You can see that I still get the same error from before. Let me fix that for a second r. See the feedback is really quick. So now I've solved my maintainability problem because if tomorrow I add a parameter or something changes in my constructor, I only have to change one place instead of 50 tests. So that's a good thing. But I've created another problem in the process. And that problem is [\[58:22\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3502s) The serial killer problem again. Sorry. Imagine that this is the bottom of a really long file. The serial killer looks at this and says C.add add. Where did C come from? Where did you initialize it? Do I get the same instance every time? I have to do this. I hate hovering with my mouse over variables. Where is my axe? So, you don't want that. We want the reader to always be able to see the test and understand anything they need just from looking at the test, not to look in two places. [\[58:55\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3535s) And here, I'm forcing them to look in two places. So, I don't like to use setups for that. Instead, what I'm going to do is I'm going to declare my calculator directly inside my test equals need my calculator, but instead of refactoring it to a setup, I'm going to refactor it to a factory method. [\[59:26\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3566s) So, Ctrl Alt M in my case a method get new C. You can name it whatever way you want as long as it implies to the reader you're getting a new instance of a calculator. So now I've solved the maintain maintainability problem because I just need to change one place. I just need to make sure that all tests never created directly. you just get a factor. [\[59:57\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3597s) And I've also solved the readability problem because the reader knows that C is always new. If they want to, they can go and look, but they don't need to. They just need to know what is what is C. Sometimes the ReSharper will tell me use var and to which I will say no, I don't want to use var. Never tell me that because in tests if you use var now you don't know what is the type that is returned from the factory method. So it's I I would suggest not to use it. [\[1:00:29\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3629s) Let's just run the tests again. Make sure everything's great. Awesome. So now I have a maintainable readable test. Questions so far? >> Yeah. If you I will call it call C my later and use what >> sorry >> you can use bar and have a better name >> I can have a better name for C >> yeah it might >> that's true [\[1:01:01\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3661s) But then what's the point the same thing >> yeah but >> just because it could have a a different name from the actual type because the actual type has to be there. The name could can be a million things. So, it's it's something that so much depends on the style of the person writing the test that I wouldn't recommend to allow VAR at all. It's like a red line. Once you cross it, you can just go crazy. Okay. So, I'm not even going to let that that that hole in the fence. [\[1:01:35\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3695s) But I can see what you mean. Maybe I would do it if I had a lot of experience and all my team would be as consistent as I am. Okay. But it's much easier to say never use var say has a variable name as the same name as the type that you're creating. Okay. >> Okay. Other questions? >> Yeah. When you were running the test >> Mhm. >> and it worked >> Sure. >> you only got like what was it in the bottom? It's like one pass. [\[1:02:05\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3725s) >> Mhm. You don't get the output when it's passed or you only get the output when it failed or what? >> I always get the output. >> But when it failed, you get like, you know, the sum was three. Your result was three, but the sum was four. >> Yes. >> But now you don't get that >> because I don't have any errors. >> Yeah, that's what I'm asking. >> So I only I only get output for errors that happened. I don't see all the tests that were executed cuz maybe I have 4,000 tests. >> Yeah. >> Okay. But if you really want to know that you know you have to like trust your test and that it's passes when >> you have to trust your test and now that's the reason where TDD really helps because you you felt the test fail and you felt it pass so you actually trust it. [\[1:02:46\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3766s) So cuz you he's your friend now cuz you you you passed something together, right? And like you wrote it and then it passes and then okay, let's debug it just in case. >> No, it actually failed. You went through something with that test. You know it. >> Okay. Okay. Okay, could you please run it run using ReSharper so we can see the difference? >> So ReSharper has a nicer view. You can see that's the difference. ReSharper you will know all the things that were executed. [\[1:03:16\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3796s) >> So what is the benefit with the TestDriven.NET? Is it only speed or? >> Well for me the benefit is that it feels faster. I don't know if it's actually faster. It's cleaner in terms of output. I just care something failed. I don't need to know about everything that I executed. So this feels like almost like like a waste. Why did I have to go through painting all these colors? You know, all these things take time. And when I'm doing TDD, the cycle can sometimes be seconds. Okay, this go fixed alt Run get the output. [\[1:03:46\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3826s) Okay, I just need to know one line of code. If there is more than one line, I just need to know what failed. Okay. But I will admit that some people like this better and I have no problem with that. This so you will find your own your own your own taste. For me there is one extra benefit to TestDriven.NET that ReSharper doesn't do and that's that's one of the main reasons that I have it installed always. So what if you wanted to debug something with ReSharper? [\[1:04:16\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3856s) You would put a break point here, say debug, and you would break into the test. Awesome. Not a problem. Not a problem. As I said, okay. I have no idea why it's not P. Oh, there it is. Easy. Okay. So, I can go through and just do whatever I need. If you wanted to do the same with test driven, you would say test with debugger. [\[1:04:53\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3893s) Same thing. So that's not a problem either. What TestDriven.NET allows also is to debug production code without tests. So I can actually go into this method here, put a break point and say right click test with debugger. And if I have parameters, they will get the default value. But I don't need a test. I don't need a console. I don't need anything to start debugging production code. So if I need to send in parameter values, I can either change them in the watch window or I can create my own like private [\[1:05:29\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3929s) Void test and add one and two. Okay. put a break point here and say test with debugger. So I have an entry point where wherever I need it. So that's a really helpful thing. Okay, no tests needed. That's one of the cool features that I like about it. Okay, [\[1:06:00\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3960s) Other questions >> in the test. So I mean I see the logic manufacturer method but what would you use setup for? >> Okay. So I would use setup for when I have maybe static singleton somewhere that I need to reset before each test stuff like that that all tests need to have a clean system. But if you cannot you cannot reset an instance of a singleton. So you has to reset it manually. So either in a setup or a [tear down](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_171 "Setting up and tearing down (The Art of Unit Testing, 3rd ed., ch. 9)") method which is the opposite of setup. [\[1:06:32\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=3992s) Happens after each test. Okay, that's the only times I would use setup and tear down. >> But say like you have five tests, each of the tests will use a database connection set up like test the database connection. >> Okay, so >> if I have tests that use database connections, I would not call them unit test. I would put them in a separate project called integration tests. And integration test, I will probably use setup for a lot more stuff because I need to set up database connections and all that. [\[1:07:02\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4022s) This might be a good time to talk about the differences. So what is a unit test now that we know what kind of what it looks like and feels like a unit test is something that runs only in memory. It doesn't touch file system or at least not directly as not specifically by us wanting it. It doesn't touch databases, web services. It runs fast. It's automated. It's repeatable. It's always the same. So if for example if you use daytime now in your unit test then every time you run it it's a different test because it's always a different daytime now. [\[1:07:39\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4059s) So you should use hard-coded values instead of dynamic values should not use random numbers. You should use always the same inputs. Now I'm not saying that randoms and daytime now are bad. I'm just saying that for a unit test they will change the meaning of what the test does every time. A unit test is always repeatable the same way it was. You can do these randoms and all that in integration tests. So integration test is everything else. Okay, they can run slower because they have database connections. [\[1:08:09\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4089s) They have more dependencies. And the separation is important because what we want is to have a [safe green zone](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec2 "Mapping out tests based on speed and type (The Art of Unit Testing, 2nd ed., ch. 7)") for our developers. So the scenario that I'm looking for is that a developer comes to work this morning, gets the latest version from source control. What do you guys use? TFS >> get >> subversion >> subversion. Awesome. So you get the latest version from subversion and you have a test project and you right click and you run all the tests in that project and they should all be passing. [\[1:08:41\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4121s) There are there are no integration tests whatsoever. They're only unit test. And because they're unit test, they're only in memory. There are no dependencies. Everything is under your control. They should all be passing. And if one of them is not, you should really feel concerned. Should actually be worried. Okay, what happens if you mix up unit in integration tests? Well, integration tests have a lot of dependencies. So, sometimes your computer doesn't have a database or a connection or you're not connected to the Outlook server or a caching or web service or that crap. So, you run all the tests and some of them fail and then someone comes to you and says it's okay, don't worry about it. [\[1:09:17\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4157s) You're just missing a database connection. So you just go on with your life thinking that you have better things to do than fix that failing test because you assume that it's failing for the wrong reason. So you don't trust the results of the entire test run. We want to be able to trust the result. So maybe some of them are actually failing for the right reason and we don't know. So at the very least by separating we have a unit test project that should be green 100% so that at least we know that a subset of them are working and we fully trust the results. [\[1:09:50\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4190s) Now with integration test project we would have maybe instructions on how to make sure that all the tests pass for that project but we expect some of them to fail usually on a new machine. For a unit test we expect them never to fail. there's a big difference in the expectations. Okay. And that's the difference between trust and no trust in that regard is that if you feel the need to debug again, then it means you don't really trust the results. So I want developers to have that green zone. [\[1:10:23\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4223s) That's my speech about integration versus unit. Any questions about that? Okay. Another important attribute that we need to learn about nunit is first of all let me clean this up. What happens if we have this kind of logic? If a is smaller than zero, [\[1:11:03\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4263s) Is not going to give me negatives. Okay, let's say we have this logic. How do we test this logic? We could just run all the tests. Oh, so I what I did is alt R is rerun the test or it repeats the last action. We're just going to rerun all the tests here. So now Alt R will always do this method, this technique. If I want to write a test for this, I'm going to need to check that it throws an exception. But before I'm going to write a new test, I realize that if I'm going to write a new test, I'm going to have to write all this crap again. [\[1:11:39\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4299s) So, let me create a snippet with ReSharper so that I don't have to do that. I'm going to copy all this. Go to the ReSharper live templates. Create a user template. We'll see what that means in a second. Now, what I want is that every time I type the word test and press tab, I get this. Okay, just an empty test for now. So, I control S to save. And now if I do test, you can see that I can see it here. [\[1:12:14\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4334s) If I type tab, I get this. It's better than nothing, but still not good enough. So I'm I'm going to go to my template and I'm going to make this dynamic. So I'm going to put to make something dynamic in my template, I'm going to put it with two dollar signs. So dollar here, dollar here. Now it's dynamic. I go back to my code. and I type tab, I get this. That's awesome. So, I'm just going to go back, [\[1:12:44\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4364s) Make everything else dynamic as well. So, that I'm going to make this the this is the unit scenario and what am I left with? result expected behavior cuz sometimes you don't get a result. Sometimes something changes in the system. [\[1:13:15\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4395s) Expected behavior. Just to make things just a little more perfect, I'm going to use a special word called end. And this is my where my cursor will end up. So now I write test and I have this. So we want to test add with first param negative should throw [\[1:13:45\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4425s) Enter and I get here. Okay. So now writing a test isn't such a great big work anymore. I was going to use worse words but this is recorded. Okay. So this is an example of how I would name something that's supposed to throw an exception. If I if it's important what's in the message, I might also add that. So one way to do it the the way Java developers used to do something like that for example is [\[1:14:18\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4458s) Get new cal extract variable C C do add the first parameter should be a negative. So what should I send in? >> Minus one. >> Minus one. It's the closest one to zero. That's negative. So the first one that's negative. What should be the second one? >> One. >> Zero. >> Two. [\[1:14:51\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4491s) Remember the serial killer. You see this? What do you see? >> Y is one. >> Why not Q is one? Because -1 and 1 seems very magical. - 1 and 0 seems magical cuz 0 is magical. -1 and 2 seems like it's consecutive, but it's not. -1 and 3 looks weird. I don't have a good input for this. So that's where I would use any positive. Okay. Create an local variable [\[1:15:22\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4522s) Int any positive equals 1. Okay, that's where it makes sense. Because I only care about the first one. So, what does my assert look like? I don't care about the result because that line should throw an exception. So, what I can do is I can controll J to wrap something in a try catch. Catch exception E. Now, if I get the exception return, everything's great. [\[1:15:56\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4556s) Because I'm expecting an exception here. And if I get all the way down here below the catch, then I would actually say assert. So that's the pattern. It's a horrible way to write a test, but that's the pattern that we would want to have. Let's run the all the tests. to past. Of course, it's passed because the code already works. [\[1:16:26\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4586s) Let's let's see what happens if the code doesn't work. Put it in a comment. You can see that the test has failed. [Expected exception](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6 "More NUnit attributes (The Art of Unit Testing, 2nd ed., ch. 2)"). That's my message. That's the name of the test. But that's not how we want to write things. [\[1:16:56\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4616s) So nunit has a special attribute called expected exception which takes in the type of the exception that you expect. And then what you do is just you remove all that crap here. And what it does is that it runs the whole test inside one big try catch block. And it does basically what we did. [\[1:17:27\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4647s) Now if it doesn't get an exception, it fails. If it does, it passes, which is exactly it's a bit hard to think about if you've never done this before. Okay, so two passed. What happens if I don't get the exception here? Sorry. So you can see the test failing. System exception was expected. [\[1:18:06\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4686s) There's a problem with putting this whole thing as an attribute. What do you think the problem is? and he thoughts, why wouldn't I want to use that? I used to I like using this attribute, but there's a problem. I can actually get a false positive for my test. Can you imagine how >> you get another exception? >> I get an exception before I even expecting this one. So notice that the attribute is in the whole test. [\[1:18:37\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4717s) So maybe get new kelp throws an exception. So suddenly my test is passing even though the line that I'm testing never got executed. So that's a big problem. This is a trust issue. Okay, it's a trust issue because any line in the test can throw it. So even though you have expected exception, don't use it. Instead, what we want to do is to use Assert.Throws. Who here has experience with using lambda expressions? [\[1:19:08\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4748s) Okay, sum. Okay, so I'm going to explain how it how it works because it's important to know to know this for this syntax. First of all, this is what it would look like if you wrote things in .NET 2. Assert throws type of exception. And the parameter assert throws takes in is a delegate. [\[1:19:40\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4780s) So it could be a delegate to a method. For example, I can create a method like this. And this method would basically execute this line. Okay? And if the whole method threw an exception, then I would I would the test would pass. However, if I did the whole thing in a separate method, I would still need to create the instance of the calculator and still I would have the same problem as before. Any line there could throw the exception. [\[1:20:10\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4810s) So, it's not a good idea to create your own method there. Instead, what I can do is I can create a delegate. Now, what's nice about anonymous delegates like this or anonymous methods is that I can take this line as is and even though it's in the scope of an anonymous method, it will actually know about the instances outside of this scope. [\[1:20:43\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4843s) Okay. So now I only have one line that's being tested to throw an exception. If any other line gets throws an exception, then my test will actually fail. Let me run this first. Two passed. Let's see what happens if I don't throw the exception again. [\[1:21:15\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4875s) Okay, failed expected system exception but was null. What happens if I throw an exception here? Throw new exception. My test actually failed. System exception, right? It doesn't care about this exception. It only cares when that line throws an exception. So how do we move from delegates to lambda expressions? You can think of lambda expressions as just a simpler way to use that or shorter shorter delegate notation. [\[1:21:53\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4913s) ReSharper will help you with this. I'll just hold enter to lambda. Looks like this. So what does it look like? It's a method that doesn't have a name. So it doesn't have any parameters. So inside the braces, you're not going to see any parameters. After the arrow is the body of the method that can only have one line. If I wanted the method to have more than a single line, I can do this. So now it kind of looks again like a delegate. [\[1:22:24\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4944s) Now, if I replace the whole thing with delegate, we're back. Okay. So, it's just a shorter notation and then I don't have to do the the the semicolon and all that stuff. So, some people find this more readable. I actually find the other way more readable. As long as you're consistent, it doesn't really matter which style you use. Okay, so I actually I will actually go back and ask ReSharper to use an anonymous method instead. [\[1:23:01\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=4981s) Okay, I know it's just more readable to me this way. Questions about throwing exceptions and asserts. so now that we have a basic working understanding of unit testing, we know some things about readability and about maintainability and about trust. We can maybe start talking a little bit about testdriven development. [\[1:23:31\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5011s) Let's see if I forgot anything. Oh yeah, just just another note about tear down. Tear down. If you do find yourself using something like this tear down, remember tearown is something that gets executed after each test. So if we look at the tests after and after, well, how do you know it was after? [\[1:24:01\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5041s) Going to have to trust me on that one. the single >> to reset singleton instances, static instances? When else would you use it? To clean out system files, stuff like that. Okay. [\[1:24:32\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5072s) But if you're cleaning out system files, it usually means what you have is not a unit test. So, I would say that if you're looking at someone else's test and I would highly recommend that you review other people's tests to learn from and to teach and you see them using a tear down, 80% of the time it's not because they're cleaning out statics. Okay? 80% of the time is because they're cleaning out stuff and it's so it's like a tell that they're doing integration testing. So if you see a tear down most of the time it means that maybe there is one or two integration tests mixed in and again the the point is so that we can separate them. [\[1:25:12\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5112s) Okay. So what we're going to do now when is the break just so I know. >> Oh it's 11. >> It's okay. So we still have >> Yeah. We're going to go check on it. >> Okay. So what we're going to know, we're going to talk a little bit about TDD. Let's see if I forgot anything. Test room development can actually make mean many things. [\[1:25:43\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5143s) Some people call TDD test driven design, some people call it test-driven development. Some people say TDD, but they just mean that they have a lot of tests, so they actually write them after. So the definition really changes among many people. The definition, the way I use this word is that we write test first. We might have some design up front, although not a lot, just enough to get us started to fill in the blanks with TDD. [\[1:26:14\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5174s) And the design could change over time. Okay. Some people will say that it's test-driven design in the purest form. If you don't have any design up front, you just start with a failing test and see what happens. Realistically, I've never done this on a real project with no design up front. So I can't say that I've succeeded with something like that. I know that some people have, but some people have not. Some people have failed with no design up front. The design they came up with was bit convoluted and stuff like that. [\[1:26:46\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5206s) So there is no one way to try this. But we're what we're going to talk about right now is the process of driving new code given that you might have some notion of what things could look like. But it's going to be really really flowing. So we could change things as time as as as we realize that. Another thing to understand about this process is that it feels very forced. So sometimes it feels stupid. But there are three types of learnings, [\[1:27:18\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5238s) Three levels when you learn something new. The first thing is that when you learn something new, the best way is to to copy the actions of someone else almost blindly, even if you feel stupid. The second level is to understand why you're doing the things you're doing, why they make sense. The third level is to improvise, to actually change the way you work, but keep the concepts that you already know the same. So for example, you might start out with TDD just making things work with simple rules sometimes not realizing that there is benefit behind these rules. [\[1:27:53\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5273s) Eventually you're going to come up to to to realize that it actually helpful. And later you might say, you know what, now that I know this and I know the concepts, I don't like the way that you taught us to write tests. I like BDD better. Awesome. So then you will have the same concepts. you will just use a different way to express them. For example, the naming convention that I use is just a naming convention. The three parts of knowledge in the name still exist if you do BDD. Okay? They still exist in most other forms if you choose to test in any other way. [\[1:28:26\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5306s) But you will improvise and you will find a way to make sure that these things exist. So that's the third level of learning. First we have to talk about the practices and what are the simple rules that we that we're looking for to make sure that we stay on the road and as we go on I will explain the benefits and the reasons and the concepts behind them so with TDD we start with a failing test that means that as far as we're concerned production code is read only we cannot change production code that is we cannot change functionality [\[1:29:01\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5341s) We can refactor So we can rename a method but we cannot change what it does. So no functional code without a failing test. If I see you writing code and I don't see a failing test, I'm going to ask you what the hell are you doing? The second part is once you have a failing test, that is you made it compile, you saw it fail, you make the test pass without touching the test. Okay? So if you're changing the test to make it pass, you're lying to yourself. Okay? So if your test is expecting three and you're getting two and you're just changing the assert to expect two, you're doing it wrong. [\[1:29:38\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5378s) You should not touch the test and it should magically pass as you change the production code. The third part is refactoring. So now that you have a passing test and all the other tests are passing, you can go ahead and refactor the code. What's the definition of refactoring? Refactoring is changing existing code without changing the functionality of that code. So if you rename a method, that's refactoring. [\[1:30:08\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5408s) If you take a long method and you extract it into five private methods, that's refactoring as well. There are tools to help with it, but it's just a concept. You don't have to have a tool to do refactoring. You do refactoring because when you solve things, when you made the tests pass, you made it pass as simply as possible, which is possibly the most difficult thing you're ever going to try to attempt if you have a lot of experience. Because simplicity is something that goes against our instincts when we try to write code. [\[1:30:39\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5439s) We try to write a code that is generic that answers a lot of possibilities that makes very little assumptions about what's supposed to happen always checks what's going to happen on its own and reacts dynamically. When we're doing TDD, I actually try to make as many assumptions as possible about the tests and make the code as dumb as possible and as simple as possible. Which is very unintuitive. [\[1:31:11\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5471s) However, this simplicity leads to several results. It makes us think about tests that we would never have thought about before. Gets us better code coverage and it keeps our code simpler than we thought we could. Sometimes we work on such a complex piece of code when we don't need to and then it's not ready on time and then we have to move on to the next test when it could have been done already. Okay. So, because we plan for the future so much, make it better is about taking all that simplicity that might look pretty ugly now because you just solved things just trying to make things work and you make them readable. [\[1:31:50\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5510s) You make them maintainable. Okay? You don't change the functionality though. So, the the the first part and the second part, you can actually treat yourself to two different people if you really want to think about it that way. The person writing the test is someone who really cares about quality and wants to prove that there is something wrong with the system. They want to prove that there is a feature missing. For example, the ad method is missing from the system. That's a bug. Or the ad method only handles the first parameter when dealing with negatives. [\[1:32:22\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5542s) Doesn't handle the second parameter. That's a bug. So they write a test that fails that proves that it's a bug because if the bug didn't exist then the test would pass. The person making the test pass is a very different person. Two ways to describe it's the laziest developer in the world who needs to go home in 5 minutes. They just need to make all the tests pass in those five minutes. What is the simplest thing they could do to make all of them pass? [\[1:32:55\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5575s) Or you can think about it, it's like your kid brother or your your your 11year-old nephew who just learned programming. How would they solve it? Okay, the simplest way possible in a very naive way. So two different people making the test and making it pass is what's required in a way. It's like a mind shift and that's a very tough thing to to do but it's part of the learning TDD. [\[1:33:27\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5607s) Okay. So what we're going to do is we're going to add a feature using testdriven development. The feature we're going to add is a missing feature because right now we're only taking care of the first parameter. So what we want to do is we want to add the feature for the second parameter. The only difference right now is that we all the code is already built for us. So all we need is to create a failing test that recreates the bug. [\[1:33:58\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5638s) And most of the time what happens is especially if you work on an existing project. You find the bug, you want to do something with TDD. The first thing you want to do is you try to recreate the bug with a failing test. That's a good way to learn TDD because it's much easier to know that you have a bug that you actually have to prove and write a failing test than to start a new feature. So let's see what it feels like. So we know that only a is taken care of. So what we're going to do is we're going to write another test [\[1:34:29\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5669s) Unit add the scenario is second param negative and the expected behavior is >> for us. Okay. So get new calc extract the variable C. Assert throws an exception [\[1:35:01\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5701s) Control shift space to help me generate this stuff. And I'm gonna say C do add any positive and minus one. Okay. And yeah. [\[1:35:40\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5740s) Is it better to declare it here or before the assert throws? Any thoughts? >> Before or? >> Why? >> Because that can throw an exception. >> A range. >> Can declaring an in throw an exception? What do you think? >> Usually no. Although it feels better, it feels more right to do it here. So I would do it here as well. Although if I saw this there, I wouldn't have that such a that big a problem. I'm trying to be practical, not blindly look at this. But if I saw something that could throw an exception, anything but declaring something which is like a value object, I would have a problem with that. [\[1:36:17\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5777s) >> But is it the declaration of any positive part of the range? >> It could be part of the range, but in this case, it just looks like it. But in this case, it's part of the assert because we're using it as part of the app. Sorry, we're using it in the app part. Assert throws in the only place where the act and the assert are basically in the same call. Okay. Any other time I would separate them. Okay. >> I'm actually also just thinking that just for readability, it's easier to keep the delegate method as small as possible because it's like harder to follow. [\[1:36:54\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5814s) >> That's true. That's true. I I agree with that fully. You could do this and re remember I have no problem with looking at the test and saying maybe this, maybe that, like tweaking it, making it just a bit more readable here. It's good to spend time on these things. Okay? It's this kind of attention to detail, the things that you care about so much that you just told me that makes those tests readable and [trustworthy](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7 "Trustworthy tests (The Art of Unit Testing, 3rd ed., ch. 7)"). Okay? Because you really should care about all those little things. [\[1:37:24\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5844s) So, it's really good to hear these. >> Why do you have throw and throws? >> You bastard. >> That's just a small one. >> That's true. I actually noticed this when I wrote it. I said, "Shouldn't be throw. It should be throws." Awesome. Good. Good. Good catch. What else? Okay, let's just run this. It should fail. Now, if it didn't fail, what would that mean? >> You failed. [\[1:37:55\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5875s) I haven't failed. I actually succeeded if it didn't fail. Why? Because I found the bug either in my understanding of what I'm trying to test or in the test. Okay? So, this is actually a win for me if this did not fail first. If it failed first, it's also a win for me because now I get to fix it. Okay? Either way, it's a good thing because doing the failure first gets me an understanding of that I'm actually understanding the problem. Okay, a lot of times we jump into something without really understanding what it is we're trying to solve. [\[1:38:30\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5910s) Okay, so we expected blah but was not. So now we need to go ahead and jump. Now the code has become read write not read only. Go ahead and jump into that. Let's see if F12 will work. Nope. What's the simplest way for me to make all the tests pass? Now I'm the world's laziest developer. What do you think? What What would your nephew do? [\[1:39:00\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5940s) What would Jesus do, etc. All that stuff. What would I do? What do you think? Can I just change it to B? I can't because another test will fail. And I know this. If I didn't know this, I might do it and see what happens. That's what one of the nice things about tests. Maybe I would realize that the first parameter doesn't need to be negative anymore. Something in the system changed. Who cares? But I can try. I can I can do a what if. Say, what if I do this? [\[1:39:30\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=5970s) What if I move this to the first line? Okay, nothing happened. Still works. Awesome. So what should I do? >> I know it seems obvious. I know it seems obvious. Or >> Hold on. I'm sure it's here somewhere. >> It's not. >> It's right there. >> It's horrible. [\[1:40:07\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6007s) Okay, close. Okay, so that was a really easy fix and now we fixed the bug. So that's that's what it looks like in the most happiest path. We didn't need to change anything about our habits and sometimes it will feel like that. Okay. But let's try to add a feature for this where it will also remember the last result. Okay. [\[1:40:38\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6038s) So if I add something and I get back a three, I want to be able to have some kind of property or a method that tells me what was the last result that was returned. Sounds good. So let's add that using TDD. So first of all, I cannot change this code anymore. All my tests are passive. Actually, I would say it's logical step because I mean what I'm thinking now is maintainability because I'm thinking all of a sudden add is a very bad name this method. [\[1:41:09\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6069s) >> It should be add positive numbers or something. >> Okay, >> how do I maintain the tests now? Because I do want to rename the method. So that's where the refactoring tools come in. If you want to rename this method, you just press F2, say add positives, you run the tests. >> Now it should compile. >> Oh, cuz it's smart enough to change all the colors as well. >> Okay. So it's not that bad. [\[1:41:39\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6099s) Okay. So you can see that add positives. >> Yeah, but I was I'm thinking yeah, that matter. But now the test methods shouldn't be add second negative. >> That's true. >> Add positive. Yes. So now we're in. >> That's true. But in that case, you can go ahead and just find and replace everything that's add underscore. That's where the naming convention also helps because you always have the underscore between those two. And it helps because it's structured. So for example, other things that this structure brings, you want to look at all the tests. [\[1:42:11\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6131s) You see them all here and they're structured by the name. So you see all the tests for a specific method or unit structured by the name as well. So you can look for it this way. It's just easier. I haven't met cases where it was that big of a problem. I have met cases where you broke a whole bunch of scenarios because you you removed the whole feature from the system and that's where you actually have to start working just remove some of the tests because they don't matter anymore. But that's that's something you can live with because it doesn't happen that often. [\[1:42:50\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6170s) Okay, so we wanted to add a feature that remembers the last the last numbers that were the last result that was added. So if I were to get a design up front, then I would know the name of this method or a property. If I didn't, I can just make it up. And that's one of the nice thing. If it's small enough, then I don't need a design for it. I can just use TDD to design something that I would want to use. So here's an example test. [\[1:43:20\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6200s) What is the unit of work if I want to add something that remembers the last value that was replied or resulted? Is it the add method? What do you think? Well, it can no longer just be the ad method because it has to be more than a single method. Okay. But what we can do is we can name the unit or the unit of work in this case into [\[1:43:51\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6231s) Result memory. So it's no longer the name of a method, it's the name of a feature in the system. Okay? You can choose to name it however you want as long as you're consistent. that once it's a feature then the feature is named in a specific way. For me I can just name it result memory and for me it makes sense. For some people it would make sense to name it as the name of the method and some other extra stuff after it. But that is between you and your project team. [\[1:44:24\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6264s) So result memory calling add. Notice that now I have to say calling add result is saved for later. Okay, I'm not saying where it's saved yet. I can I can say this if I have a design. So for example, I can say result is saved in last result property or something like that. So I can do that as well. [\[1:44:55\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6295s) So the naming can be kind of elastic. You can change it based on what you know or don't know yet. So get new cal extract variable. See you can see that it's not a big deal. I try not to copy tests from one test to the other. Copying tests results a lot of times in really messy tests because you don't know what to remove or you forget because you're new to this stuff. So you end up with more mess. So it's better to to learn to make yourself more productive. [\[1:45:26\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6326s) Maybe add a snippet for the asserts etc. You can add a snippet for creating a calculator. Right? No one prevents you from doing that. So C do add positives. Do we care about the positives? Do we care which positives it is? Then we just use we care only for the assert. But the do the positives mean anything in this in this scenario? [\[1:45:56\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6356s) Doesn't mean doesn't say which positives. So it's any positive. So we'll use the default values. Okay. I don't care about the result. Actually I do care about the result. Maybe there are se several ways I can check this. I can assert that the result is equal to what's happened there. I can check that what h what what is in that other property is equal to three. two good ways. Both of them are pretty readable. I would love to know what you think about both of them. [\[1:46:26\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6386s) But here's the part where I say if I could do anything with the system, how would I want to assert something like that? Cuz it doesn't exist yet. So I'm playing God right now. Okay, I can do whatever I need. So assert as if everything you need is already there. So it might not even compile. Assert are equal let's say three for now [\[1:46:56\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6416s) And C dot last result. Okay. So what I'm doing here, I'm not even going to make it compile first. I'm just looking at this test right now. Sometimes I'm going to get the parts that don't compile at the beginning, the range part. [\[1:47:29\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6449s) Sometime I'm going to get them in the assert. Sometimes I might have multiple things that don't compile. The important thing here is that I'm using something that doesn't exist yet. And I'm not going to make the test compile until I fully finish writing the whole test. Okay? So I might have several red things here, but I'm not going to bother making them compile until I'm happy with the way this test is written because this is a stage that I get to say, you know what, let's result is not a really good name or maybe so it should be a method [\[1:48:00\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6480s) That takes a parameter maybe I'm missing something here and changing it while it doesn't exist yet has zero cost because it doesn't exist yet. Okay. So what we want is here to define what is success. Success is being able to do this, do that and all that stuff and getting better result. Now that I've defined success and I'm happy with the way this test is written and I'm happy with the way the API looks and feels then I can make it compile and see it fail. [\[1:48:30\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6510s) Okay, this is a design phase because in this design suddenly I am the user of my new API. So I get to feel what it's like to use it. So I get to change it if it's not usable. For example, if I have parameter orders and I say, you know what, the big number should be first and the the lower number should be second. Feels more natural to me. And I could change it if that method didn't exist yet. So it's a design issue. If I'm happy with the way the design looks, [\[1:49:01\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6541s) I just alt enter to create it. So I can choose it as a property. I can choose it as a field. I'm assuming it's going to be a property. Make it an auto property. Okay, now that it's compiling, I'm going to make it fail. That is, it should fail by default cuz I haven't added any code to make it not fail. Okay, so expected three but was zero. So, we've just passed [\[1:49:33\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6573s) The first stage. Now, we get to be the world's laziest programmer. We have 5 minutes to to go to lunch. What is it that we want to do? >> Make the test work. >> Yeah, we want to make all the tests work. So, how can we make them work in the simplest way possible? [\[1:50:05\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6605s) >> It's just hard code the results. >> Are you sure? >> I know you're using one and two for the whole. >> Yeah, that's true. Is that something you can live with? >> Yeah, just for you know just for the just just to entertain you. I'm going to do that. How do I return it from a get method? Let's turn it into a property with a backing field. Hey, you know what? Like this. >> Yeah. [\[1:50:37\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6637s) >> Awesome. >> World's best programmer. However, if I run all the tests. Okay, I guess the feature is working. >> There I fixed it. There's actually a blog of people who fix things this way. So this is awesome. Why is this awesome? First of all, it's awesome because I got to be the world's laziest developer for a second. [\[1:51:08\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6668s) That felt good. Second is that this is horrible. And it's horrible, but I cannot change it because I don't have any failing test unfortunately. So if I want to change this horrible thing, I need to have a failing test first because that's the first rule of TDD, right? So this is read only. I wish I could change it, but you need to prove to me that something's wrong. So now I have to write another test that proves to me that I need to change it. [\[1:51:42\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6702s) Okay, first rule of TDD. Okay, so if I cannot change it, what should I do? >> Create a test. create a new test. And what would this new test do? Exactly the same thing but with a different input. So it would expect a different value. So if I'm going to write the same test twice and it's the same test just different inputs and outputs, what I can do is I can use another feature of nunit which is called test case. [\[1:52:15\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6735s) So instead of test I'm going to change it into test case and test case accepts parameters which get sent in as parameters into the test so that my test case right now is one and two and it expects three. Where did I get the one and two? I'm going to extract a parameter here. We'll call it a. And you can see a in the parameter list now. [\[1:52:46\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6766s) Call this B and this is going to be the expected. So now we just wrote the same test only now it's parameterized. So the first value here goes to the first parameter. Second value goes to the second parameter. And what's cool about this is that I can have multiple attributes on the same test. So I can do this one and three equals four. Why did I use one and three? because I can see the pattern one and two one and three. [\[1:53:18\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6798s) So my brain sees this and said okay that's the next logical thing. I can also say if I did one and two and then two and two it's the same input. So I don't want to use that. Now if I run all the tests actually now I have two tests running here. So I say expected four but was three and you can see also tells me which of those cases were broken. If you use ReSharper it tells you that there are two tests here. [\[1:53:48\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6828s) Okay, so now I have a failing test that tells me that what I did was a bad assumption because that's what essentially I did. My assumption here was that I always need to return three because I'm always going to get one and two. Bad assumption. So, what I'm going to do is I'm going to undo the last result and I'm going to do the simplest thing could possibly work to make all the tests pass. [\[1:54:22\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6862s) Last result equals a plus b. That make sense? The ReSharper tells me, "Dude, this this will never work. So, you might as well do this." Now, I could refactor to return last result, but that's too many actions to do. If I can just do it in one action, why not? Let's run all the tests. [\[1:54:52\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6892s) They will pass. Now, I get to refactor. I say, you know what? That's not good enough. Let's just return last result here. So, return last result. rerun all the tests, make sure I didn't break anything. Now, this is kind of the beginning of where TDD might might take us. It's a very simple method with very simple inputs and outputs, but it starts to I I I'm hoping you get to start to understand what it feels like to do a little bit of it. [\[1:55:27\]](https://www.youtube.com/watch?v=WWZR6vq6BvU&t=6927s) Any questions so far? >> Nothing. Okay. So, let's take >> like 15 minutes. >> Yeah, 15 minute break. >> there's actually this pika in the kitchen. >> Mhm. >> Pika pika. ## Related - [The pillars of good unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8) · The Art of Unit Testing, 2nd ed., ch. 8 The 2nd edition's chapter on trustworthy, maintainable and readable tests, the three properties this lesson builds on. - [Naming standards for unit tests](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html) · osherove.com Roy's post on the three-part UnitOfWork\_StateUnderTest\_ExpectedBehavior test name used for the calculator tests. - [Avoid setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162) · The Art of Unit Testing, 3rd ed., ch. 8 The 3rd edition's section on avoiding setup methods, the reason the lesson uses factory methods instead. - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6) · The Art of Unit Testing, 2nd ed., ch. 1 The 2nd edition's section on test-driven development: failing test, simplest passing code, then refactoring, as done here. - [Definition of a Unit Test](https://www.artofunittesting.com/definition-of-a-unit-test) · artofunittesting.com Roy's definition of a unit test and its properties, including how it differs from an integration test. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [What is a good unit test?](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_23), ch. 1 - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 - [Maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8), ch. 8 - [How to know you trust a test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134), ch. 7 - [Trying the factory method route](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2), ch. 2 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [The Art of Unit Testing, Third Edition](https://www.manning.com/books/the-art-of-unit-testing-third-edition) - [The xUnit frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39), ch. 2 - [The library, the assert, the runner, and the reporter](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_37), ch. 2 - [Naming unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_168), ch. 9 - [Defining isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99), ch. 5 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [How can we know we don’t have bugs in our tests?](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11), ch. 11 - [Setting up and tearing down](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_171), ch. 9 - [Trustworthy tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7), ch. 7 #### The Art of Unit Testing, 2nd ed. - [First steps with NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3), ch. 2 - [More NUnit attributes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6), ch. 2 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1), ch. 1 - [Properties of a good unit test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec2), ch. 1 - [Writing readable tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec3), ch. 8 - [Writing maintainable tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec2), ch. 8 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec3), ch. 1 - [Automated builds running automated tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec1), ch. 7 - [Mapping out tests based on speed and type](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec2), ch. 7 #### osherove.com - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) - [Test Coverage and testing angles](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html) - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) - [BDD: Behavior vs. Spec Frameworks](https://osherove.com/blog/2008/10/4/bdd-behavior-vs-spec-frameworks.html) - [How to do test reviews](https://osherove.com/videos/2011/2/6/how-to-do-test-reviews.html) [Next lesson Test Driving a String Calculator](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-driving-a-string-calculator/) --- title: "Test Driving a String Calculator" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-driving-a-string-calculator.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-driving-a-string-calculator/" tags: [] author: "Roy Osherove" description: "Lesson 2 of 14 in The Art of Unit Testing & TDD Master Class in .NET (The Basics), 27:29. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Test Driving a String Calculator 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 3. The Basics Lesson 2 of 14 Duration: 27:29 [Watch on YouTube](https://www.youtube.com/watch?v=C81hzgSVy1w) Roy Test Drives the creation of a [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)") with explanations on best practices. ## In this lesson Roy Osherove introduces [code katas](https://www.5whys.com/articles/how-to-measure-programmer-productivity-using-tdd-katas.html "How to measure programmer productivity using TDD Katas (5whys.com)") for practicing [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") and starts the [string calculator kata](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)"), whose Add method returns the sum of the comma-separated numbers in a string. He writes one test at a time, starting with an empty string returning zero, and makes each pass in the [simplest way](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)"), from always returning zero to int.Parse, finding a bug on the way. He runs the tests with NCover, saying [coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)") means little without [test reviews](https://osherove.com/videos/2011/2/6/how-to-do-test-reviews.html "How to do test reviews (osherove.com)"), and sends the audience to do the kata [in pairs](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html "How Do You Explain Pair Programming? (osherove.com)"). ## Transcript 3,692 words [\[00:04\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=4s) Okay. So with that I want to introduce to you the idea of a [code kata](https://www.5whys.com/articles/how-to-measure-programmer-productivity-using-tdd-katas.html "How to measure programmer productivity using TDD Katas (5whys.com)"). Who here has heard of this katas for code? One person that's that's a good start. Code katas are exercises that you can do in code. But this kata is special for [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6 "Test-driven development (The Art of Unit Testing, 2nd ed., ch. 1)") purposes. If you want to learn how to do TDD, most of it is about muscle memory. Okay, it's really easy to learn the theory, but if you want to learn TDD for real, you have to exercise with it. [\[00:37\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=37s) You have to do it. One of the katas that I would recommend is a simple one called a [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)"). If you go to osherove.com you might see this description over here and the idea of the kata is to create a simple calculator class. [\[01:07\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=67s) It has one method that only takes one parameter and it's a string. That string can contain zero or more numbers divided with a comma and it returns the sum of all the numbers that it finds. That's the whole idea. As you progress through the the exercises, it gets more and more complicated. So more and more demands on how on what needs to happen, more features requested. You should think about this as a project that every day you get a new feature that you never thought of. [\[01:39\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=99s) So try not to read ahead if you ever do the kata. We will later we'll do take a 30 minutes and try to do it ourselves as pairs so you can feel what it's like. It's a good way to practice TDD because it's not very complicated. It's more about learning through your fingers how to do something. In the page itself, you can see a lot of videos on how to on how other people exercise the kata in basically all of the recent languages. [\[02:09\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=129s) So, Java, Ruby, C, Erlang, Scheme, Haskell, couple of them in Perl and PHP. So, and there is one in JavaScript actually. So, you can see how it's done in JavaScript as well. And what I'm going to do is I'm going to show you the first steps of the kata right now so you can see the TDD process although you already know some of it and after that I'm going to you're going to try it yourselves. [\[02:39\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=159s) So I'm going to assume that every two people here will have at least one laptop because the exercise is done [in pairs](https://osherove.com/blog/2003/9/9/pair-programming-qampa.html "Pair Programming Q&A (osherove.com)"). So the first thing we do when we start the kata is we start with a blank solution. Now, if I if this was my three or five day TDD course, I would actually tell people disconnect your mouse from your machines and try to do the whole thing without a mouse just for the added difficulty just to make it a bit more fun. But for now, don't worry about it. So, [\[03:10\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=190s) If I create a new solution, oh, that's not a new website. I just want a new solution. And I choose other project types. Empty solution, blank solution. I call it kata. And in the kata, I add a new project class library. We're going to call it [\[03:41\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=221s) Kata.ests because we don't have any [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)") here. Now because it's TDD we start with test first. So the first requirement in the kata is create a simple string calculator with this method. It can return zero or more it can return zero for an empty string or the sum of numbers if there are any numbers in the string. [\[04:14\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=254s) So I'm starting with the tests. So, first thing I'm going to do is I'm going to rename this into string calculator tests because that's the name of my class. I'm also going to set the package manager. So, I'm going to so I I'm going to save time later by investing a little time right now. Package going to look for package manager console and I'm going to give it a shortcut alt n [\[04:46\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=286s) It's not taken I'm just going to assign it from now on whenever I need to install something I just press alt n install package [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)") so that will save me some of the work later now I have all the references I'm going to remove two of these And because I don't need them and [\[05:20\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=320s) This one. No. >> Oh, I'm in English. That's why. >> Okay. Test fixture. Start with a test. The first test and this is sometimes we face this dilemma. We could write a lot of different tests for this method. So which one should we write first? So the answer is if we want to work in an incremental fashion, which is usually what we want to do, we start with the [simplest test](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") that will drive us to create something in the simplest way. [\[05:53\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=353s) So if we have a set of demands such as it can return zero for an empty string, it can return a number for a single number, it can send it two numbers or 15 numbers. Which one of them is the simplest requirement to implement? What do you think? >> Empty string. >> Empty string. It just feels simpler, right? Sometimes you don't know but it feels like this is the smallest thing. [\[06:24\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=384s) It it's also incrementally the beginning of a feature. You can start with numbers but you might forget to do an empty string later. So we can start with add empty string because add is the name of the method and the expected behavior is returns zero. So for added returns zero for an empty string. So now we can create the class. [\[06:55\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=415s) Remember the class in this case doesn't exist yet, not just the method. So I might say string calculator which doesn't exist yet. And I'm not going to make it compile until I finish the whole test. SC equals new string calculator. I'm not going to refactor this because I don't have two tests that use the constructor yet. The point here with TDD is to drive new functionality. So I don't worry about refactoring the test yet until I have two passing tests. [\[07:27\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=447s) SC.add empty string. Okay. Introduce a variable int result and assert. Now there are two types of syntaxes for nunit which I only showed you one of them. You can do assert r equal but there's also assert that result [\[07:58\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=478s) Is and then we have multiple things equal to zero. So some people like this syntax better. It's your choice as long as you're consistent. I personally like the first one but a lot of people like this one. To me, this is less readable than just assert or equal. But it's just a choice. You should know that this exists. So, I'm going to do assert. You know what? Let's just keep it this way. [\[08:30\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=510s) So, now if I'm happy with the test, I'm going to make it compile and I'm going to see it fail. To make it compile, I'm not even going to create the separate product project. I'm just going to create it right here beneath my test. Create a class. Create a method. Now I the default of the of the variable names are not good. So I'm just going to change them to be more readable numbers. Should I keep this or not? [\[09:01\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=541s) What do you think? >> Except exception or what? >> Yeah, throw new not implemented exception. Some people like to keep this so they can see the test fail. I personally like to see the test fail on something that feels like the real system. So, I'm actually going to return a bad value on purpose. Return minus one. It just feels better to me. I don't have a good explanation why this makes more sense. [\[09:32\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=572s) Both of these will work, but this is closer to the solution that we need. This feels more like a bug that I would want to fix. Maybe that's my my explanation. So now that I have this, I can go and for just once right click and run the test in this project. And of course it fails. And that's awesome. [\[10:02\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=602s) And now I get to fix it in the simplest way possible. Remember laziest developer in the world has to go home in two minutes. What do they do? They just make as many assumptions as possible. The assumption I can make here is I'm always going to get an empty string because no one can prove otherwise yet. So I can just always return zero. And again, this is something that feels not intuitive, but the practice of simplicity is something that at the beginning you need to learn how to do to simplify your actions. [\[10:34\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=634s) Right now all this does is it it proves to us that we're missing more tests because we're not happy with this code. So what we're going to do since this code is not read only, you have to write another test. So I'm going to write another test and this time it's still the add method. The scenario is going to be something that will drive me to remove this assumption that it's always empty. Okay. So what scenario should I choose? [\[11:06\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=666s) What do you think? >> send in one. >> The number one or one number >> one string. >> One in the string. Okay. Just the number one. >> Yeah. Which number? >> One. Just one number. That is one. [\[11:41\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=701s) Never mind. Okay. U the scenario. So how would you explain this? A single number. Okay. Any number, right? A single number. A single number is simpler to prove than two numbers. So add with a single number. What should it do? >> Returns that number. Okay. So now I can say string calculator and I can already feel that I would need to refactor but only after this test passes. [\[12:13\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=733s) The point is to drive functionality that I can actually demo. Refactoring comes later. SC equals new string calculator. SCA add what is the number one? one number of one, right? Result int results assert or equal. [\[12:45\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=765s) We should expect. What should we expect? You sound very quiet. Assert that we get back one. from results. Run all the tests. One passed, one failed. We can see the results here. Expected one but was zero. I just need to look at the [test name](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html "Naming standards for unit tests (osherove.com)") to know. [\[13:15\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=795s) Okay, now we get to make everything right. The simplest thing possible to make all the tests pass. What do you think I should do now? >> Return one. return one. If I return one, it will break the first test. So, I can't do that. >> Make all the tests pass in the simplest way possible. >> Return numbers. >> Return numbers, but it's a string. It's supposed to be an int. It's supposed to return an int. >> Parse. [\[13:46\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=826s) >> Parse Make sense? int.Parse will turn a string into a number. Okay? Okay, let's run all the tests. Weird. That's weird. Could we actually have a bug in one line of code? Okay. Ed empty string return zero failed. [\[14:19\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=859s) Input string was not in the correct format, dude. Okay, so I guess we just discovered our first bug. So that was simple, but it doesn't work. So what do we have to do? What should we do? What do you think? Obviously, it means that int.Parse doesn't work with empty strings. Okay, so we need to make the simplest thing but still pass all the tests. So that doesn't work. >> Try parse. Try parse is an if it's the same thing. [\[14:50\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=890s) Try parse most people don't know it so I'm going to use a a different way if numbers length is zero let's return zero okay otherwise what should I do you know you know what I'm going to do right >> parse it >> parse it return one. >> Can I make an assumption here? [\[15:22\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=922s) >> Return one. >> I can make an assumption. If it's not anti- string, it's always one. >> Horrible. Horrible. Two passed. Unfortunately, I can't change this now. >> So, if you wanted me to fix this, we're going to have to have another test. But before we do that, let's make the test a bit more [maintainable](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)"). So, I'm going to extract this into a [factory method](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "Trying the factory method route (The Art of Unit Testing, 3rd ed., ch. 2)"). Method make calc. [\[15:53\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=953s) Same thing here. Run all the tests again to make sure I didn't break anything. That's why I want all the tests to be passing. But if I change the test and something breaks, I know that it's because of my change. If I refactor the test while something is breaking, I won't know it's it's breaking because of my changes or it's breaking because it always breaks. So, I want to always have a clean sheet. a a sheet of knowledge. Okay. So we have concluded this is not great. [\[16:27\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=987s) I'm assuming that you're not happy with this code. So what we're going to do is we're going to prove that we cannot make an assumption that the number is always one. To do that we can just go here and turn this into a test case. So for example I'm going to make this into a parameter alt p. This is the numbers. Control Alt P. This is the expected. Go to test case. Send in one. Expect one. [\[16:58\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1018s) Just run all the tests again. Okay, two passed. Duplicate with control D. What number should I send in? >> Two. >> Two. Perfect. Run all the tests. Gotcha. Okay. expected two but was one. Okay, I guess I can't hide anymore with my with my assumptions that it's always one. So, what should I do? What's the simplest way to make all the tests pass? [\[17:36\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1056s) Someone once suggested you just do an if. If it's a one, you return one. If it's a two, you return two. But that's not as simple as just int.Parse. it's not as simple. So what's the difference? Simple is shorter. Simple is less indentation. If I need to do an if, I have more indentation, right? So visually, I can actually say that something is simpler than something else. If it's more to the left than the other thing, for example, if it's closer to the beginning of the method, it's simpler than if it's the bottom of the method. But in this case, this might be everything I need in parse. [\[18:09\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1089s) Sometimes the the actual solution is a solution. Okay, but it took us three tries to get here. So, parse numbers, run all the tests. Three pass. Now, several interesting things here. First of all, if my manager comes in and says, got a demo for me, I can actually tell them, look, it's partially working. It's working for an empty string and it's working for single numbers. [\[18:41\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1121s) It's actually partially working. It's incremental developments. It doesn't work with multiple numbers yet, but it will. So if I can say that something works now 10 minutes after, it means that if I chose to release today, I would have a partial release. If I'm working in iterations of two weeks then and I'm working in micro iterations like this of every few minutes it means that every two weeks the the release day is just another day because every day every hour we have something we had that we didn't have an hour before [\[19:12\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1152s) Because it always working. That's a big difference from working on something for three days and it's not working at all. Then suddenly it works right and you're always in the 95% working. It's almost working like 95%. Just another 90% to go. Okay, that so you should never feel like that again. If you work in an incremental way, you always have something to to return. The simplicity goes toward that feeling. [\[19:43\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1183s) Okay, so I guess that's working. But you know what? Maybe I can make another assumption that I didn't consider. For example, and this is one thing that sometimes I force myself to do, although I don't expect you to remember to do it on your own. Sometimes it works to remember it, sometimes it doesn't. I can make an assumption about the length of the number if I wanted to. So, I can say numbers are always one character, right? So, I can parse the numbers just the first character. [\[20:15\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1215s) I don't care about anything else, the string. all the tests will still pass. Although I added code to make this happen. However, if I do this, it forces me to write another test that says numbers can be more than one character. And if I don't do this, I don't even consider writing that test. A lot of times we don't think about tests that seem obvious. But for now, this just a thinking point. Here's another thing you can do. [\[20:46\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1246s) Test with NCover. So NCover is a free tool. This is an older version. It's a free tool that tells you the [coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)") details of something. Right now we have 100% code coverage. Okay, in our tests and in our code. If you work in the in the that incremental way in the simplest way possible then every piece of code that you do has a reason to exist because a test expected it. [\[21:16\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1276s) So that every piece of code is covered. So you should expect 95 to 100% code coverage if you do the things this way. Having said that high code coverage doesn't mean anything. Okay? If I tell you that I have 100% code coverage or if you tell me we have 100% code coverage, that doesn't mean anything to me because maybe all your tests don't even have asserts. Okay, so code coverage doesn't mean that you have quality. It just mean that you have code coverage. [\[21:47\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1307s) However, low low code coverage, 20% code coverage means something. What does it mean? We have 20% code coverage. What does it mean? >> We're missing tests. That's all it means. 100% doesn't mean anything. It only means something if you do [test reviews](https://www.artofunittesting.com/unit-testing-review-guidelines "Test Review Guidelines (artofunittesting.com)"). If you look at each other's tests and you review them to make sure that the tests are good. If I know that your tests are good, then 100% means something. [\[22:18\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1338s) But if I don't know that your tests are good, then 100% is meaningless. So as a goal, if you ever had a goal to strive for coverage, it should be to strive for coverage plus test reviews. Okay? Because when you only have the goal of coverage, then as developers, we are only aimed at just having a test that does something. We're not aimed at quality. If we have test coverage, then the test will be good and the coverage will mean something. [\[22:48\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1368s) So I can go on with this. For example, I can say, okay, what if I give you more than a single number because right now you assume that you can parse the number. But if I have two numbers, I'm pretty sure you can't parse that because there's a comma in between them. So add with multiple numbers. Why didn't I just add it to the previous one? Why do you think? Think about that for a second. We'll talk about that in a second as well. [\[23:20\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1400s) Multiple numbers The difference is in the scenario. Okay. So if someone reads multiple test cases, the serial set and they see one, two, and then suddenly like weird stuff, there is no explanation why that weird stuff exists in those parameters. The name of the test should explain generically everything [\[23:50\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1430s) That the test cases above it do. If it doesn't, for example, it says single number, but my I have some inputs with multiple numbers. It doesn't make sense. So either I change the scenario, but I don't want to change it because this is a specific feature to handle a single number. It's a different feature to handle multiple numbers because I'm working incrementally. So now I can say make calc exact variable and that should be sc [\[24:21\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1461s) Add and again the simplest numbers would be one and two in results are equal we're expecting three from result run all the tests this time it's going to run with coverage because that's the last action that I You can see 86%. Because something failed. Okay, I'm going to run them without coverage. Now [\[24:52\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1492s) It says input string was not in correct format just for multiple numbers. So now I have to do the simplest thing that could possibly work and make all the tests pass. Any ideas? Split the string. >> Split the string. >> Yeah. Okay. So, but then will it know how to handle a single number if I split the string? [\[25:24\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1524s) >> Okay. So, here's what I want you guys to do. Split into pairs. Two people on one machine. You switch. Every time one person writes a test, the other person solves the test. Okay? One person is lazy, the other is not. And then you switch the next time. Try to do the kata on your own. Get all the way to this situation. Try to solve it on your own in the simplest way possible. Okay? If you're working in JavaScript, do it in JavaScript. [\[25:54\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1554s) There's a there's a framework called Jasmine, which I recommend. I I'm not a JavaScript developer yet so I'm not going to be able to help you but setting up the environment might be a good learning opportunity for you anyway. Okay. If you're doing in .NET do the things that I did in .NET. Any questions before we get started. >> Okay. So let's take 30 minutes and see where we get in 30 minutes and I'll just run around and look at how you write code and give you various tips and tricks. [\[26:27\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1587s) Okay. >> Good luck. Let's be careful out there. [\[27:13\]](https://www.youtube.com/watch?v=C81hzgSVy1w&t=1633s) >> So, if you don't remember the URL, It's ## Related - [TDD Kata 1 - String Calculator](https://osherove.com/tdd-kata-1) · osherove.com The original String Calculator kata the lesson starts, with its requirements listed one step at a time. - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) · osherove.com Four questions for finding the simplest thing that could possibly work, the rule Roy follows for each passing step. - [Comments on Corey Haines’ String Calculator TDD Kata Implementation](https://osherove.com/blog/2009/12/23/comments-on-corey-haines-string-calculator-tdd-kata-implemen.html) · osherove.com Roy's comments on another developer's recorded run of this same String Calculator kata. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8), ch. 8 - [Trying the factory method route](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2), ch. 2 #### The Art of Unit Testing, 2nd ed. - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6), ch. 1 - [First steps with NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3), ch. 2 #### osherove.com - [Test Coverage and testing angles](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html) - [How to do test reviews](https://osherove.com/videos/2011/2/6/how-to-do-test-reviews.html) - [How Do You Explain Pair Programming?](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html) - [Pair Programming Q&A](https://osherove.com/blog/2003/9/9/pair-programming-qampa.html) - [Naming standards for unit tests](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html) #### 5whys.com - [How to measure programmer productivity using TDD Katas](https://www.5whys.com/articles/how-to-measure-programmer-productivity-using-tdd-katas.html) #### artofunittesting.com - [Test Review Guidelines](https://www.artofunittesting.com/unit-testing-review-guidelines) [Previous lesson Unit Testing And TDD 101](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/unit-testing-and-tdd-101/) [Next lesson Test Driving a Console Application Using String Calculator](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-driving-a-console-application-using-string-calculator/) --- title: "Test Driving a Console Application Using String Calculator" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-driving-a-console-application-using-string-calculator.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-driving-a-console-application-using-string-calculator/" tags: [] author: "Roy Osherove" description: "Lesson 3 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Fakes, Mocks and Stubs), 16:54. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Test Driving a Console Application Using String Calculator 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 3. Fakes, Mocks and Stubs Lesson 3 of 14 Duration: 16:54 [Watch on YouTube](https://www.youtube.com/watch?v=wyN6iznigrY) In this talk, Roy adds a new layer to the application, and uses the existing [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)"), integrated and used from inside a console application. It is also the first time the idea of a [mock object](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") is introduced. ## In this lesson Roy Osherove test-drives a console application that uses the [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)") by calling its Main method in memory from a [unit test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)"), after making Program and Main public. He mentions compiler flags and the [InternalsVisibleTo attribute](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6 "Overcoming the encapsulation problem (The Art of Unit Testing, 2nd ed., ch. 3)") for keeping members hidden, then redirects console output with Console.SetOut to a StringWriter over a StringBuilder and checks it with StringAssert. The aim is to connect the string calculator layer to the console layer with a couple of tests, and he moves the console replacement into a [helper method](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6 "Building a test API for your application (The Art of Unit Testing, 2nd ed., ch. 7)"). ## Transcript 2,224 words [\[00:26\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=26s) Yesterday we and now we you all have a a very basic version of the [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)"). What we're going to do now is we're going to try to do to attempt to create a console application that uses the string calculator. Okay. So we're going to try and do it with a [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)"). We're going to try to do a test first. But first, I want to explain how how my design cho choices are going to work. So to understand how to test first a console application, let's see what a console application looks like. [\[01:00\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=60s) So if I go to my solution and I create add new project console application, I'm going to call it string master cuz I want to be able to say string master.exe. What is the structure of the string master? Well, it has a program class. It's not public. It has a main method, which is the main entry point. Let's get rid of this. [\[01:31\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=91s) And that's not public either. Now, if I want to test drive giving inputs to a console application, instead of creating a new process, etc., I can simply use in-memory calls from my [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1 "Defining unit testing, step by step (The Art of Unit Testing, 2nd ed., ch. 1)") to actually call this method, the main method. So if I wanted to try and do this, so let's say I would create a new class here and I'd call it usually I'd put this class in a separate project called string master tests or string master unit tests. [\[02:06\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=126s) In fact, you know what? Let's do that. Add new project class library string master unit tests. You don't have to do it. You can just watch for now because you're going to do the whole thing later anyway. For now, it's important that you just get the concept and the idea of what do I what's optional and what what can I actually change to make things more testable. [\[02:40\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=160s) I'll just rename this class. And since what I'm going to test is program, the program class, I'm going to say program tests. Also let's set the NuGet package. So, package manager console install package nunit. [\[03:16\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=196s) Okay, let's create the test fixture. Test fixture. Create a new test. Now in this test, the [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") is main cuz that's the main static method cuz that's my entry point. And I'm not going to expect to do anything else but just call the entry point and then check that there was some kind of output to the screen. And we're going to find out how to do that. So main now a basic scenario how do I prove that if I send in some inputs to the main method it actually uses string calculator to write to the screen. [\[03:53\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=233s) Well remember on the first day I said I don't want to I treat everything between the inputs and the outputs as a black box. So I don't care if it uses string calculator or not. I just care that something was written to the console that is the result. And then I'll just hook up all the internal stuff to make the result happen. So I can say two numbers and [\[04:24\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=264s) Writes their sum to the console console. Writes is maybe it's not writes but it calls the console with their sum. The reason I'm using the word calls here is because I can't really use the real console. I'm not going to test this visually. So the console is in fact some kind of dependency, something that I cannot control. [\[04:55\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=295s) So, I'm going to have to somehow replace it or I'm just instead of checking that it the console writes something, I'm just checking that the console was called with the correct parameters because if it was called with correct parameters, I can assume that the UI looks the way I want it to look because I don't have control of the UI. I can just replace it with something else. So I use the word calls to to say that there is that the [end result](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)") is a call to an external system instead of just returns something or throws an exception or changes state. [\[05:31\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=331s) Now it's a call to an external system that's beyond my control which is a user interface of some sort. Now if I wanted to just call main if I just say program there's no such thing because program is not public. If I go to program I can actually make it public and personally I don't have any program in pro problem in making program public because it's an entry point anyway. [\[06:03\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=363s) It's not like it has to be hidden. It's a console application. Now if I go here, ReSharper will tell me, hey, do you want to just reference and use program? I'm going to say yes. But now main is not public either. So I'm going to make it public to make it more visible. So I can actually invoke it. Now again, because this is an entry point, it shouldn't be a problem at all. It's an entry point, so anyone should be able to invoke it. [\[06:33\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=393s) It would just wasn't currently meant for the use of unit test. So I'm just making it usable by unit tests. But in other cases where I make things public, maybe it's more of a security risk. Maybe there's a problem there. And in that case, maybe in terms of design I can choose to make things public because I think it's a better design. Or if I think it's not a good design to make it public, but for [testability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec1 "Why should I care about testability in my design? (The Art of Unit Testing, 2nd ed., ch. 11)") I want it to be, I can put it inside [\[07:04\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=424s) What do you call these? If like debug or if test like this and if so now only during my tests will this thing be public and callable. So I can put things in in compiler flags if I wanted to hide them. Another possibility if I wanted to make things unhidden [\[07:35\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=455s) Is to not make them public but make them internal. Now internal means that it's public only to the current assembly. But I can also add a special attribute in the in the properties of the project inside assembly info CS and kind of say this assembly [InternalsVisibleTo](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6 "Overcoming the encapsulation problem (The Art of Unit Testing, 2nd ed., ch. 3)") [\[08:11\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=491s) My test assembly whatever the name of the assembly is. And assuming that nothing is strongly named, this should be enough. And then it will look public to a specific assembly because it's been friended. If you have an assembly that has been strongly named, then you're going to have to put the strong the public key. So it looks a bit weird. It's a bit long to generate, but it's still at the end of the day just a string that you put in this attribute. [\[08:42\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=522s) And and suddenly anything that's internal becomes public to that assembly. So you have ways around this if you still want to keep things hidden. For us right now it doesn't make any any sense not to just make it public. So if I go back to my tests now program main I can now simply in memory invoke this function. So I can say a new string with the value of one and two. [\[09:17\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=557s) Okay. In fact, I don't even need this. So now I'm able to send an input into my console application in memory and it's fully under my control. But how do I know that something was written or something was calling the console application? If I wanted to replace the console application with something else, actually in the .NET API, we have a built-in way to replace the console. [\[09:50\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=590s) Now, I'm not sure why this API exists, but probably because someone wanted to test it at the Microsoft headquarters as they wrote the thing. So, they wanted to redirect output to various sources. So what we can do is we can use a special API built in called Console.SetOut. Now Console.SetOut takes a text writer which is an abstract class. So there are multiple things inheriting from text writer. So how do I know which one I I can send? [\[10:20\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=620s) What are all the things inheriting from test text writer? This is another thing I like in ReSharper is that I can say text writer and then control alt alt h to see the hierarchy of this class or in this case let's see ReSharper inspect oh type hierarchy yeah yep that should have worked oh because I don't have a using that's why alt h now this is the text writer and [\[10:53\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=653s) What I can also do, let's see, is kind of look at this. Apparently, there's nothing that seems to be inheriting from it. Maybe I'm missing something. Cuz obviously there are things that inherit from it that I'm I'm sure there are. So let's say text writer. [\[11:28\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=688s) Hm. Interesting. I'm not sure why. Let's see. What if I just say string writer? Well, that that exists. So, I'm not sure why I'm not seeing the type hierarchy right now, but I can tell you that the string writer is an is a version of text writer. Maybe it's a bug or maybe I've just missed something right now. So, I can say string writersw equals a new string writer. Now, string writer writes to a string builder or an in-memory string. [\[12:00\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=720s) So, I can say just use my string builder here. So I'm going to create a string builder use it inside the string writer and give it the string writer. Now from now on everything that I write to the console if I do this console.Write blah my string builder is going to contain that string. [\[12:30\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=750s) The console is actually not going to be written at all. the output has been redirected. So I've I've essentially replaced the console output with my own output which is a string builder which I have full control of and it's all in memory. So now I can actually assert at the end of the test that the string builder contains a specific string. I can assert that it also equals a specific string. But that's not usually a good idea because that will make the test more fragile. usually just want to test that a string contains something because a lot of times strings are a form of UI. [\[13:05\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=785s) So they can contain extra new lines, the dates. We we care about specific things inside the string. So instead of this I'm going to say we call it with main but before that we replace because otherwise if I replace it after the call after the act it's not going to be written to then we can assert and if I wanted to assert on strings there is a a special class I can use built into nunit it's called StringAssert. [\[13:41\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=821s) It's built into I can say StringAssert and I can use contains or ends with or matches a regular expression. So StringAssert contains three from the string builder to string. Okay, I can also rename it to let's say [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") output. Maybe that's a better name. [\[14:12\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=852s) Okay, so that's an example of how I can take control of a console output and actually use it as a as a test-driven mechanism to to prove that something should be done. Now, currently, if I run this test, it's going to fail. And I want you to get to this stage where that this test actually fails and make it pass as simply as possible. But in this case what we're doing is we're not going to just use say return three because what we want the purpose of this is to connect two layers together. [\[14:49\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=889s) The purpose is to connect the string calculator layer which we built separately and in testdriven into one layer up which is this layer and we can just have a couple of tests that prove that the layer works. We don't have to write all the test for string calculator again. where what we're testing is that we can shoot one thing into the input and we get back another thing in the output and we assume that everything is actually connected because of that. We we it's okay to have some knowledge about the architecture [\[15:22\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=922s) But we don't have to care that it calls a specific string calculator class. Okay, questions. Okay, so we're going to split into a pair but it's going to have to be different. So, today you guys can, can pair up and you you'll be working alone today and tomorrow we're going to switch again. Okay. [\[15:53\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=953s) So by the way, I wanted to add one more thing in terms of refactoring to make this test. I wouldn't do all these three lines in the test. What I would do is after the test would pass is I would refactor something like this. Extract a method call it replace console and I will change the var to use a string builder to make things more readable. [\[16:23\]](https://www.youtube.com/watch?v=wyN6iznigrY&t=983s) So string builder fake output equals replace console call the program and then make sure that the fake output contains something and then I would use that I it would make the test more readable especially if I'm going to replace this multiple times. So it becomes a utility methods ## Related - [TDD Kata 2 - Interactions](https://osherove.com/tdd-kata-2) · osherove.com The follow-on String Calculator kata that adds interactions, the next step after wiring the calculator into a console app. - [Overcoming the encapsulation problem](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6) · The Art of Unit Testing, 2nd ed., ch. 3 The 2nd edition's section on the encapsulation problem, covering options like the internal visibility tricks the lesson mentions. - [Value-based vs. state-based vs. interaction testing](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec1) · The Art of Unit Testing, 2nd ed., ch. 4 The 2nd edition's section separating value, state and interaction testing, useful as the lesson starts checking console output. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19), ch. 1 #### The Art of Unit Testing, 2nd ed. - [Building a test API for your application](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6), ch. 7 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1), ch. 1 - [Why should I care about testability in my design?](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec1), ch. 11 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 #### osherove.com - [TDD Kata 1 - String Calculator](https://osherove.com/tdd-kata-1) - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) [Previous lesson Test Driving a String Calculator](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-driving-a-string-calculator/) [Next lesson Introduction to Hand Written Fakes, Mocks and Stubs](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/introduction-to-hand-written-fakes-mocks-and-stubs/) --- title: "Introduction to Hand Written Fakes, Mocks and Stubs" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/introduction-to-hand-written-fakes-mocks-and-stubs.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/introduction-to-hand-written-fakes-mocks-and-stubs/" tags: [] author: "Roy Osherove" description: "Lesson 4 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Fakes, Mocks and Stubs), 7:18. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Introduction to Hand Written Fakes, Mocks and Stubs 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 3. Fakes, Mocks and Stubs Lesson 4 of 14 Duration: 7:18 [Watch on YouTube](https://www.youtube.com/watch?v=l9X2kunieG8) Roy Introduces the idea of [mocks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4 "Interaction testing using mock objects (The Art of Unit Testing, 2nd ed., ch. 4)"), [fakes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") and [stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1 "Introducing stubs (The Art of Unit Testing, 2nd ed., ch. 3)") and shows how to [hand write them](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec7 "The problems with handwritten mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)"), and when it makes sense to hand write them. ## In this lesson With a login manager whose save method must also call a logger written by another team, Roy Osherove introduces [an ILogger interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)") so a [hand-written fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec3 "A simple handwritten mock example (The Art of Unit Testing, 2nd ed., ch. 4)") logger can replace the real one. A [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") the test asserts against is a [mock object](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)"), one it does not assert against is a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)"), and the same class can serve as either. He also explains that injecting the fake through a constructor, rather than a property, tells the user of the API the dependency is not optional. ## Transcript 1,023 words [\[00:25\]](https://www.youtube.com/watch?v=l9X2kunieG8&t=25s) So now that we've done a simple replacement of an object, let's talk about the idea of [mock objects](https://osherove.com/blog/2005/6/30/the-mock-objects-elevator-speech.html "The Mock Objects elevator speech (osherove.com)"). and [stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)"). let's talk about a more interesting case where where things are not built in where we actually have to build a UI a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") object. So imagine that you have a class called login manager. [\[00:56\]](https://www.youtube.com/watch?v=l9X2kunieG8&t=56s) Login manager already uses a logger class and there is a method called save. Now the point of the save method is to to save an object. But if an object has a property that's something that is too big for example then what we should do is we should also log the fact that there was an object that was saved that was too large. [\[01:28\]](https://www.youtube.com/watch?v=l9X2kunieG8&t=88s) So the requirement is that there are actually two requirements save and also write to the logger if there is something that happens or call the logger. Now let's assume that the logger is written by a different team. So it's actually not under our control or maybe it's actually not even done yet. Maybe it was written to maybe the code was written but it was not it's not finished yet. [\[01:58\]](https://www.youtube.com/watch?v=l9X2kunieG8&t=118s) So every time we want to actually call the logger we get an exception. So now we actually have an interesting situation where our team is depending on a different team. the team that writes the logger and we actually have to wait for them to finish the job. Or maybe the logger takes such a long time that we don't want to use it in our real tests. So instead of using the real logger, we can replace it with something else. [\[02:29\]](https://www.youtube.com/watch?v=l9X2kunieG8&t=149s) We can introduce a new interface into the system. to be able to replace something in a static language like C#, it has to inherit from some from the same object or implement the same interface. So we can introduce [an ILogger interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)"). So now instead of logger, we create a new interface and it only has one method which is write just like logger has. But now in the constructor for login manager, there's an ILogger instead of a logger. So it doesn't care which logger it uses. [\[03:01\]](https://www.youtube.com/watch?v=l9X2kunieG8&t=181s) And this ILogger is actually part of the production code. It's not part of the tests. But now because I have that interface in my tests, I can create a new class that I create by hand called fake logger. And the nice thing about fake logger is that it's actually part of the test project. So it implements the same interface, but because it's in the test project, it doesn't have to do anything. I just implement the methods and they're empty. [\[03:33\]](https://www.youtube.com/watch?v=l9X2kunieG8&t=213s) They're not really doing anything. In fact, I can also override the methods and save the values that were sent in. Okay, so I can save the values and put them in, let's say, a public field or something like that. And in my test, I can use a fake logger instead of a real one. send it to the constructor of the login manager. And now in my test, I'll create the login manager, send it to the the fake logger, call save, and then assert against the fake logger that some field contains a string or something like that. [\[04:10\]](https://www.youtube.com/watch?v=l9X2kunieG8&t=250s) Just like I did with the string builder in the previous exercise, this time there is no string builder. There is no built-in API. So I created my own API for this, something that I have full control over. So when we have a fake object and I specifically call this class a fake logger not a mock logger or sub or anything like that it's a fake logger because it can replace something but when I have a fake object that I also assert against [\[04:41\]](https://www.youtube.com/watch?v=l9X2kunieG8&t=281s) Then that's called a mock object. The concept of a mock object is that there's something fake, not real in the system. But I'm also but it also decides whether my test failed or not. So if it has the power to break my test and decide that that my test failed, then it's a mock object. But if it's a fake something and I'm not asserting against it, then it's just a stub. So there's the idea of a fake and it's either a stub or a mock based on how I use it. [\[05:13\]](https://www.youtube.com/watch?v=l9X2kunieG8&t=313s) And if I keep this class clean enough, I can reuse it to be a mock in one test and then the same class can be used as a stub in another test. That's a that's that's important because we don't want to have 15 different classes in our test projects for for a single type of object. So let's see that. This is a demo of a class called login manager. Now I called it login manager with mock but usually the word mock will not be part of production code just for demos. [\[05:55\]](https://www.youtube.com/watch?v=l9X2kunieG8&t=355s) Now I already went ahead and created the interface for ILogger here. So there's an interface for ILogger. It has just one method called write. There's also a logger exception but we don't care about that for for now. We have a constructor and here I made a design decision that I can send in the ILogger through a constructor. But I could also have chosen not to add a constructor parameter. I could have chosen to add a property or a method that takes in and sets up a private field. [\[06:28\]](https://www.youtube.com/watch?v=l9X2kunieG8&t=388s) So what's the difference? What when would I choose to use a constructor and when would I choose to use something else to inject that fake object? Any ideas? Why would I use a constructor? >> What's the difference between a constructor and a property? >> You have to put it there. >> Yeah, it's not optional. Good. I have to use the constructor. So when I put an argument as a constructor, I'm actually telling the user of my API, this is not optional. [\[07:01\]](https://www.youtube.com/watch?v=l9X2kunieG8&t=421s) You have to provide this. That's an important design decision because it means it can never be null. For example, ## Related - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2) · The Art of Unit Testing, 2nd ed., ch. 4 The 2nd edition's section on the difference between mocks and stubs, the same line drawn with the fake logger. - [A simple handwritten mock example](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 4 A simple handwritten mock example from the 2nd edition, matching the hand-written fake logger built here. - [Refactoring your design to be more testable](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec4) · The Art of Unit Testing, 2nd ed., ch. 3 The 2nd edition's section on refactoring a design for testability, including injecting fakes through the constructor. - [Mocks and Stubs - The difference is in the flow of information](https://osherove.com/blog/2007/9/16/mocks-and-stubs-the-difference-is-in-the-flow-of-information.html) · osherove.com Roy's short classroom explanation of mocks versus stubs as a difference in the flow of information. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Extracting a common interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74), ch. 3 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 #### The Art of Unit Testing, 2nd ed. - [Interaction testing using mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4), ch. 4 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 - [Introducing stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1), ch. 3 - [The problems with handwritten mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec7), ch. 4 #### osherove.com - [The Mock Objects elevator speech](https://osherove.com/blog/2005/6/30/the-mock-objects-elevator-speech.html) [Previous lesson Test Driving a Console Application Using String Calculator](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-driving-a-console-application-using-string-calculator/) [Next lesson Isolation Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/isolation-frameworks/) --- title: "Isolation Frameworks" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/isolation-frameworks.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/isolation-frameworks/" tags: [] author: "Roy Osherove" description: "Lesson 5 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Fakes, Mocks and Stubs), 1:01:27. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Isolation Frameworks 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 3. Fakes, Mocks and Stubs Lesson 5 of 14 Duration: 1:01:27 [Watch on YouTube](https://www.youtube.com/watch?v=rtAlQt2l-0s) Roy reviews the basic differences between the various [isolation (ocking) frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec1 "Why use isolation frameworks? (The Art of Unit Testing, 2nd ed., ch. 5)"). Also explained is the difference between [profiler based](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") and [proxy based](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev2sec1 "Constrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") frameworks. ## In this lesson Roy Osherove explains [isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99 "Defining isolation frameworks (The Art of Unit Testing, 3rd ed., ch. 5)"), which create [fakes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") at runtime, and divides the .NET ones into [proxy-based frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev2sec1 "Constrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") such as [Rhino Mocks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5 "Current isolation frameworks for .NET (The Art of Unit Testing, 2nd ed., ch. 5)"), [Moq](https://osherove.com/blog/2012/6/27/the-future-of-isolation-frameworks-and-how-moq-isnt-it-for-n.html "The future of Isolation frameworks, and how Moq isn't it (for now) (osherove.com)") and [FakeItEasy](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html "FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition? (osherove.com)") and [profiler-based ones](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") such as [Typemock Isolator](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html "Minimizing unit Test Fragility – 8 features in Typemock Isolator to help (osherove.com)"), [JustMock](https://osherove.com/blog/2010/5/25/justmock-and-moles-a-short-overview-for-tdd-alpha-geeks.html "JustMock and Moles – A short overview for TDD alpha geeks (osherove.com)") and Moles. Profiler-based frameworks rewrite the IL at runtime through the CLR profiler API, so they can fake static and private methods; proxy-based ones need interfaces or virtual methods. He compares their APIs on the same logger tests, from string-based [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)") Mocks to Rhino Mocks extension methods, and shows Isolator [faking static methods](https://osherove.com/blog/2012/7/8/faking-static-methods-in-moq-fakeiteasy-and-nsubstitute-migh.html "Faking static methods in Moq, FakeItEasy and NSubstitute might be closer than imagined (osherove.com)") and future instances. ## Transcript 8,711 words [\[00:28\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=28s) Okay, everyone awake? So I want to continue the discussion about [mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") and talk about some of the terminology to previews make it a bit more official and then we'll move on to [isolation frameworks](https://osherove.com/blog/2008/12/3/isolation-frameworks-lessons-from-the-wild.html "Isolation frameworks – lessons from the wild (osherove.com)"). we we reviewed the idea of [mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_79 "The importance of differentiating between mocks and stubs (The Art of Unit Testing, 3rd ed., ch. 4)"), but let's start with a a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)"). A fake [\[01:00\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=60s) Is anything that can replace anything else in the system based on how you use it. If you verify calls against it, it's a mock. Or if it can fail your test, it's a mock. Otherwise, it's a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)"). Now, a stub cannot fail your test. A stub should not throw exception unless it's so you can test something else. There are there are other ways to there are other [\[01:34\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=94s) Words to describe these things. There's a book called xUnit Test Patterns that talks about various different definitions of these fake objects and based on how much code is inside this thing whether it contains custom code or not they have a different take on the naming. So test spy double fake mock stub all mean different things within the same realm. I believe that this is too complicated. So that's why I use only three terms. [\[02:06\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=126s) The term fake, term stud, and the term mock. Everything else is not important for our purposes. Yes, based on that xUnit patterns book, you can actually look at mocks and stubs and even and and tear them apart into even smaller definitions. But for what we need, it doesn't matter because the only reason I use the ideas of mocks and stubs is so that I can review and understand if a test is oversp specifying, has more specifications than it needs to, is testing more than a single thing. [\[02:40\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=160s) And it doesn't really matter if that fake stop is halfwritten or fully automated or doesn't do anything or has a lot of logic inside it. Okay. With the manual fakes the way we've done it so far. What happens if the interface that we are creating a fake for has a lot of methods? [\[03:13\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=193s) Okay. What happens if each method has a lot of parameters? It begins to be very complic not complicated but very time consuming and actually boring to recreate very large interfaces with a lot of parameters. What if we wanted to verify that something was called more than a single time and that each time it had different values? It's not complicated to save these values into an array of some sort and then verify but it begins to be just timeconuming and boring and not important. [\[03:46\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=226s) So that's where isolation frameworks, a lot of people call them mocking frameworks. That's because the term mocking is overused. I call them isolation frameworks because you use them to isolate a unit from its dependencies. So these frameworks what they do is they allow us to save a lot of coding time by creating these fake classes for us so that we don't need to do anything but write a couple of lines of code to get an object that is fake and behaves in a specific way. [\[04:29\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=269s) Now when we're talking about the these frameworks, what they do is they usually do this all dynamically at runtime. They also do all that basic stuff like saving values, saving the parameters and all that stuff for us. And they can also simulate exceptions and all the other things we want we would want them to do. So it's just imagine that you have written unit test for many years and every day you find yourself writing the same fake class with the same fake behavior over and over. If this is exception is being said then throw it. [\[05:02\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=302s) If this is being saved then save the value, save it to an array blah blah blah. Eventually you're going to end up with some infrastructure for doing this this thing. And that's where isolation frameworks began as infrastructure. And then someone took them took that and made it even more generic. Now the this is a very important part. There are two big types of isolation frameworks and based on which type you choose you get very different abilities because they're built on very different technologies. [\[05:35\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=335s) The way I look at isolation frameworks in .NET they're they're divided into two different types. There are profilerbased frameworks. There are [proxy based](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev2sec1 "Constrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") frameworks. No one tells you this, but the frameworks have very different abilities. And I'm going to explain exactly what [profiler based](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") means. But first of all, let's look at the list here. Let's talk about proxy based because that's where most people are. Proxy based you're going to find all the familiar frameworks like [Rhino Mocks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5 "Current isolation frameworks for .NET (The Art of Unit Testing, 2nd ed., ch. 5)"), [Moq](https://osherove.com/blog/2012/6/27/the-future-of-isolation-frameworks-and-how-moq-isnt-it-for-n.html "The future of Isolation frameworks, and how Moq isn't it (for now) (osherove.com)"), etc. [\[06:06\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=366s) There's also NUnit Mocks which is a framework built into nunit with mock objects. No one uses it and no one should use it because it wasn't built to be used by the public. It was built to test NUnit itself. However, some people like to to to see the word mock and try to use it. We're actually going to see a demo of that to see why you shouldn't use it. And I've put these signs to to to tell you about frameworks that I wouldn't recommend using anymore. So I wouldn't recommend using NUnit Mocks and I wouldn't recommend using Rhino Mocks even though Rhino Mocks is actually in in the book that I wrote because with the time that I wrote it it was a good decision. [\[06:46\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=406s) Now Rhino Mocks has become a bit overloaded with a lot of different APIs. It's much more difficult or complicated to use than the other frameworks here. These days I would recommend Moq or [FakeItEasy](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html "FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition? (osherove.com)"). Some people really like NSubstitute. I don't have a problem with that. What's what's interesting is that all these frameworks are all either open source they're all open source and free. What's interesting about profilerbased frameworks is that none of them are open source [\[07:20\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=440s) And most of them are not free. So [Typemock Isolator](https://osherove.com/blog/2006/9/27/using-typemock-vs-design-for-testability.html "Using TypeMock vs. Design for testability (osherove.com)") is not free, [JustMock](https://osherove.com/blog/2010/5/25/justmock-and-moles-a-short-overview-for-tdd-alpha-geeks.html "JustMock and Moles – A short overview for TDD alpha geeks (osherove.com)") is not free. Moles is free but it's was built by Microsoft and it's not open source. Now so I'm going to talk about what profilerbased frameworks are and then I'm going to explain the the the the differences between these and we're going to see an example of the API of most of these to see that they also have very different design decisions built into the API and the design decisions also affect the usability, [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)") and [maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)") of the tests. [\[07:56\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=476s) So profilerbased frameworks they use a technology called profiler API. This is an unmanaged wrapper running around the CLR. The CLR is a runtime COM-based runtime and you can actually host your own CLR in a process if you really wanted to. The profiler APIs are an unmanaged COM-based wrapper that you can actually register to them and receive interesting events about anything that's happening inside the CLR. [\[08:35\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=515s) Now to enable the profiler APIs, you have to set up a couple of environment variables in the process that's running the CLR. That's all. Once you have these environment variables up, you you can actually register and receive a lot. I'm talking about hundreds of different events. Now these events give you a lot of power. An example is that you can get an event before or after each method gets called or executed. [\[09:06\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=546s) Another important event is before module load. A lot of the frameworks, profiler based frameworks use this because they this event actually gives you the IL at runtime before it gets compiled into binary code in memory. So the way the CLR works is that when you write code, you compile it, what you get is not a binary that contains zeros and ones is you get binaries that contain IL in bytes. [\[09:38\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=578s) And then the IL is loaded into the CLR at runtime and gets transformed into zeros and ones based on the current machine and CPU etc. So it's actually optimized for the machine it's running on. That's why sometimes people say that CLR based programs can actually run faster than C++based programs because when you compile to C++ you compile to the most lowest common denominator. you don't know what CPU you're going to run at. But here we know what CPU we're going to run at because we are on that CPU right now. [\[10:11\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=611s) So we can use special flags etc at runtime. But because of that before we before the IL gets transformed we can actually get an event and we can change the IL the intermediate language before it gets compiled. Now the IL is all the program. We can get the source for all the program including the IL for all the third party programs as well. [\[10:42\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=642s) So for example if I am writing if I'm loading a SharePoint based code not only my source code gets transformed into IL it gets the not only my IL gets transformed but the SharePoint IL gets loaded as well. So I can actually transform IL of thirdparty applications as well. So what a lot of these frameworks, the profiler based frameworks do is they not only give us API to to override and retrieve stuff, they actually transform the IL of all the methods or most of the methods that they would like to and they give us an API and and in all these methods they give us hooks that say basically is this method should this method behave as a fake method or not. [\[11:29\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=689s) So that when the program is compiled, it's compiled that every method begins and ends with a question. Should I throw an exception? Is it fake? And all these gets get hooked into managed APIs that the frameworks give us. And so now imagine that you can use the frameworks to say whenever you have a method that begins with the the letter A, it has to throw an exception. We can actually do that. Whenever you have methods that have more than three arguments, they always return false. [\[12:00\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=720s) So this is basically AOP which is the initials for aspectoriented programming. So profilerbased APIs give us the ability to do aspectoriented programming. It just happens to use AOP to fake specific behavior of methods and objects. Now because of that we can fake the behavior of any method we ever want. Static methods, private methods, static constructors, whatever you want cuz everything is IL really. [\[12:32\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=752s) There is no prevention or limitation on the behavior you would want including for example the behavior of date time. You can say the daytime now always returns the year 2000 if you really wanted to. And in fact in most of these frameworks you can actually do that. You can say set date time now to be the year 2000. And that's so profilerbased frameworks are notoriously hard to write because they're they have unmanaged profiler APIs. [\[13:05\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=785s) The profiler APIs have little or no documentation. It's as if they have security by offiscation, if you will. But the offiscation is not intentional. It's just neglected. And whoever gets this magic potion can create their own framework that can do basically anything. So now when we get back to profilerbased frameworks, what's interesting about these profilerbased frameworks like Typemock Isolator, JustMock and Moles is that they all allow you to fake whatever you want. [\[13:40\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=820s) And that's very different from proxy based frameworks. And I'm going to explain what proxy based frameworks are in a second. But proxy based frameworks by default have much less abilities because they do not use the profiler based APIs. They cannot change the behavior of everything. They only change the behavior of things that you can [inherit and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") just like we did in manual code. So in terms of profilerbased frameworks, Typemock Isolator is the oldest one. It ex it's it's been in existence for at least seven years I think or even eight. [\[14:16\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=856s) And it's a very mature product. I used to work there. I worked there for about 3 years as CTO but it existed way before I joined. And I helped create one of the APIs that you will see. And I quit that place about a year ago because I wanted to find my some my my roots in different places. But it's it's an amazingly powerful product and it's been in use for a long time. So, it has been matured. It's been going through basically any scenario a customer would need and and mostly working for anything. [\[14:52\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=892s) Now JustMock is a relatively new cover about two years maybe and JustMock has mo I would say probably 60% of the abilities that you can do with Typemock Isolator not not because it doesn't use the profiler based API it does it basically they both have the same potential to do anything but they expose different abilities okay to expose all the abilities in in a managed API in a usable way is very difficult. [\[15:25\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=925s) So JustMock as a relatively new product has a lot of abilities but it keeps adding more and more abilities. It has not yet kept up with the abilities of isolator. It also costs about half of isolator. So as as as we're talking right now isolator is costing about $800 per seat which is a lot of money but in [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") situations it's amazingly useful when you cannot change code. You can fake whatever you want. Just cost about half of that. [\[15:56\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=956s) And Moles is interesting. It's it's actually free and it's part of a tool called Pex which generates unit tests based on conditions it sees in your code. But I would not recommend using this framework at any cost because the API is not meant as an isolation framework. The API is meant only for faking things, not for verification. And it's a very unusable API. It's almost an afterthought. So if you use this API, what you get back is unmaintainable and unreadable tests. [\[16:30\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=990s) So it looks cool at the beginning, but then it it it deteriorates very quickly. Also, the way you use it is that you point it at an assembly, then you generate two types of objects from it. There are stub objects and there are mole object. Stub objects basically work almost like proxy based or just like we did manually where we created something that inherits or implements an interface and then override all these things and then the mold objects are for all the things that you would use isolator JustMock for all the things that you cannot fake with proxy based statics etc and they these APIs look different that's very confusing and very annoying to learn [\[17:14\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1034s) So I would I would recommend to stay away from it, but you have to know that it exists. So you can stay away from it. So it's not really free. It's just free by definition, but it's not free when you when you work with it. It actually cost you a lot of time. Time equals money. So let's move over to proxy based frameworks. Proxy based frameworks most of them depend basically on the idea of a proxy inside .NET. There's an ability to create classes which proxy other classes. [\[17:46\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1066s) They look like them and they and you can actually generate code that looks like a specific interface or a class. But most of these take it one step further. They use a a framework called castle.proxy or Castle DynamicProxy. And this this library uses all that what I just said the proxy ideas in .NET. But the way it does it, it basically they all generate code that inherits [\[18:16\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1096s) Or overrides code just like we did manually. So let's say that you had [an ILogger interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)"). You can use e any of these proxy based frameworks to create a class that inherits from the ILogger interface override and saves the values and and whatever. But it happens in at runtime. You don't really get a new class in your code. Now you can do all these things with isolator and JustMock as well. It just doesn't happen the same way because because they use a profiler. So it looks like it's done the same way but in reality it will work on any method on that on that class. [\[18:53\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1133s) So you don't have to have an interface to fake something with a profilerbased framework. You have to have an interface or a class with virtual methods that you can override with proxy based frameworks. So essentially anything that wouldn't compile if you had done it manually you cannot do with a proxy based framework because it does what you did manually does it automatically. Yes. Would you if you invest in a license for a profiler based framework would you only use it or would would you still use the the proxy based well because as far as I've seen the syntax might be a bit more accessible or something at times. [\[19:31\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1171s) We had this question because we consider to get probably just because we have a Telerik license we could upgrade to that and the problem is so are we using two or one so what is what's your opinion on that >> well if you have a choice and you can use two frameworks or one framework I would go with one framework >> because in terms of learning you you want to have the same API throughout your test it's better >> so all the the profile will do both abilities so it's better to use one. [\[20:01\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1201s) Now JustMock kind of has a two two modes. They have like a free mode that works like a proxy based framework and they have a non-free mode that works like a profilerbased framework. So it's it's kind of like you get JustMock but you don't really get the abilities of profiler based until you actually pay something. >> Okay. And Typemock used to have such a mode, but it doesn't have that anymore. [\[20:31\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1231s) So, you you get it and you get everything included. Okay. So, what we're going to see, we're going to see examples of of nunit Rhino Mocks and FakeItEasy. And then we're going to see isolator. I don't have examples with Moles and JustMock because isolator is my specialty. Although I've used both of the other ones I think that I don't want to overburden you with too much information. [\[21:04\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1264s) So and also again I don't have any agreements with any of the companies etc. It's all just my personal beliefs. Okay. So let's see a demo. So what we did so far is we we've seen manually how we can how we can actually [\[21:36\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1296s) Create fake loggers manually. Let's look at NUnit Mocks and see why some people really like it even though they're not supposed to use it. So this is the the simplest the simplest elevation above from manual fakes as you can think of. Instead of creating a fake logger class, what I do is I add a reference to any mock dl and I create a class called dynamic mock [\[22:06\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1326s) And instead of creating a class, I say new dynamic mock and I give it the type to implement. Then I tell the my dynamic mock to expect a call on a method called write with the value called yo. Notice that it's all string based and that's one of the big differences from all the other frameworks which are newer. They're not string based anymore. So string based is a problem in terms of refactoring. [\[22:38\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1358s) If my method changes later it's a problem. So I say look I want you to expect write with yo now at the end I will just say mocklog.verify verify but where is the fake instance coming from I will say mocklogmach instance and I will cast it into ILogger okay so at runtime what's going to be what's going to happen is that it's going to generate in mock instance a class that actually inherits from ILogger implements all the methods saves all the values and does whatever it needs to do and it generates it at runtime compiles it in memory and gives gives us the the instance. [\[23:18\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1398s) So it will actually match logger interface and that's pretty cool because it saves us some work. So this is the same class we use login manager with mock. We give it an ILogger which is the mock instance. The mock instance is going to behave based on how we told its parent how to behave to expect write yo with this value. Then we can say mocklog.verify verify and that will go through all the expectations. I can have multiple expectations on what could happen [\[23:50\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1430s) And if one of them didn't happen, it's going to fail. Or if one of them happened with a different value, it's going to fail. I'm going to get an exception. Okay, here's the same example, but this time with two dependencies. Create a dynamic mock of ILogger and call it stub logger. create a dynamic mock of IWebService call it mock service these are two fake objects [\[24:20\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1460s) Okay but it's called dynamic mock because the idea of fakes versus stuff is not in the API so the name of the variable that I use is now very important because that's the only way to tell that that that's how I intend to use the object now if I wanted to simulate an exception I will tell the stublog expect and throw on method Right? Always throw a logger exception. Okay? When you get yo [\[24:51\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1491s) On mock service, I say just expect write and got exception. Now notice that I'm I'm only doing at the end I'm only doing one verify. I'm not doing two because one of them is a stub. I'm not going to verify against it. I don't want to assert that it got called. I'm only going to assert that the mock service got called. The stub logger is going to throw something, but I'm not going to verify that it got called. Okay? Because I don't care if it got called. [\[25:21\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1521s) I just care that it simulated something. So, if it didn't get called tomorrow and everything still worked just the same, my test will not break because what I care about is just the [end result](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)"), which is this. Okay? So we have a stub logger expect and throw expect here and then we initialize login manager with mock and stub with an ILogger of the stub logger and an i web service of the mock service. [\[25:54\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1554s) Both of them we get the mock instance here. And you can see the tool tip says it returns object but at runtime that object can be cast into the specific interfaces. Okay. Any questions so far? Okay. So are there any benefits or pros or cons that you can see with this API? >> Anything you like about it? >> No. >> You don't like anything about it? I must admit yeah well the one thing I instantly see is this the problem with the string that you mentioned and the other thing is that in the verify I don't see what I'm verifying because it's in the expectation. [\[26:40\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1600s) >> So you don't see what you verify at the end because it actually happens in the beginning the the expectation and the fact that it uses strings so the refactoring might be a problem later. >> Yes. >> Okay. I agree. But I also want you to notice that there is a design decision here that we have basically two things that we interact with. We have the the dynamic mock object which is basically the parent. That's the thing that you set all the expectations on. [\[27:11\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1631s) And then you have the actual fake object which is from mock instance. So we have a parent and the actual fake. And there are two separate objects. And that's a design decision. Okay. And the reason I'm I'm telling you to focus on this because we're going to see different designs very soon and they're not going to look anything like that. Some of them will, some of them won't. Okay. So, that was NUnit Mocks. And again, this is not recommended to be used. This is just an example to show the history of how frameworks have basically evolved since then. [\[27:47\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1667s) Okay. And I agree that the fact that the expectations are here, the verification is here, it's kind of hard to read. Okay, let's look at Rhino Mocks. This is how you would write the same test with Rhino Mocks. So let's go through this. To create an ILogger, let's make this like this. We basically call a static class called mock repository and we say generate mock. [\[28:21\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1701s) It also has a generate stub method. Now this time the method is generic. So it doesn't return object and what we get back is directly the fake object of the type. There is no parent that we set the expectations on. Okay. And then we say okay initialize login manager with the mock and send it the mock logger. And now suddenly we have a method on that ILogger interface called assert was called given the logger [\[28:54\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1734s) Which is the fake logger. Did something like this happen to that fake logger? So the refriation is at the end and where did assert was called come from? That's an extension method. Okay. So what we see here is that actually arrange act and assert behave like we used to do before. So in terms of readability it's definitely nicer. Now assert was called is an extension method. [\[29:26\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1766s) It means that there is there are extension methods on the type of object in this API. And that's both good and bad. It's good because now you can go to the fake object directly and say assert that you were called and it will fail if it wasn't. But it's also a problem because in terms of API if I go and I say something [\[29:57\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1797s) So something and I say dot I can actually do a search was called on something that's not even fake. And that's a problem. It's actually confusing. I don't want to I don't want my IDE to tell me that I can do things that I shouldn't and in fact I shouldn't do this. But because the design decision was use extension methods at the object level then everything gets this this method and that's a problem. So, as far as I'm concerned, I have a problem with this API because it basically [\[30:36\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1836s) It it make it dirties up the IntelliSense name space of all the objects. That doesn't mean that I like the older design better, but I definitely don't like this one. This is the same test with two dependencies. One is a stub, the other is a mock. Create a stub logger with mock repository. Generate stub. And this is interesting about generate stub. Even if you assert was called on a stub, it still would never fail. That's a design decision and that's something that or an ammy [\[31:11\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1871s) Actually caught at some point. Then we can say I want you to expect and this time again we're not using strings anymore if you've noticed I want you to expect what we have is actually a lambda expression and the way I read this lambda expression because we have to satisfy the compiler I want you to expect and this is another extension method okay so expect on a logger which is the fake logger [\[31:43\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1903s) Expect this call to happen logger.Write write with yo that means that I'm expecting exactly yo to be sent in and if I wanted to do something different like expect any string we can also do that with write or mock and when that happens I want you to do throw a new logger exception so the expectation is actually a way for me to set up throwing an exception it's not really an expectation I will assert against. [\[32:18\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1938s) But the API doesn't make this too clear. It says expect and then it says throw. And expect by nature means expected. So it might need to be verified later. But really here it means when this call happens through this exception. No need to verify. Then we have the mock service. We generate a mock and at the end we will verify a new mock service. The search was called that the service.Write [\[32:53\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=1973s) Got exception. Okay, the service right was called with this value. So we initialize login manager with the stub log and the mock service just like we did before but the assert look very different. So in this design we all we have extension methods on object and we have expectations and asserts directly on all objects in the system. It's our responsibility to make sure that you write the calls on the correct objects. [\[33:25\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2005s) So so if you're going to use an ID with IntelliSense you're as far as I'm concerned the API doesn't use the strength of the IDE to help the user in terms of usability. it actually confuses the user more. Are there any questions or thoughts about this API? Now, this is basically the latest version of the API. It used to have an older version where you would do what's called a record and replay scenario where you would record what's going to happen. [\[33:59\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2039s) Then you would say, "Okay, now go into replay mode." And then it would behave the way you recorded it before. So you would say record call write and then return three and then replay and now somewhere inside someone would call it it will return three but record replay turned out to be not so usable. I mean a lot of people liked it but then arrange act assert came in and it's much more usable. Okay, [\[34:29\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2069s) Questions before we move on. Now, Rhino Mocks is very much used around the world. So, it's good to know this API. Now, the Moq or the Moq is the first package that that actually came in with the idea of arrange act assert for isolation frameworks. I think it was the first and Rhino Mocks was the first to come in and and remove the idea of strings from methods by using delegates like we saw before. [\[35:03\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2103s) Moq was the first to say let's do a range act assert at the at the at the at the test level instead of record replay. So here's how we write the first test with Moq. With Moq when we want to override a class or create a fake one, we will say create a mock of ILogger. It's always a mock. Even if you're going to create a stub, it's still called a mock. Okay, so this is again a parent [\[35:36\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2136s) That you tell what to to do. So create a mock parent really of ILogger. And then you would use mocklog.object object which is just like mock instance from NUnit Mocks and this time we don't have to cast it to ILogger because it's generic and because it's generic it's already the right type [\[36:07\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2167s) Now here at the last line I have verification and verification I've made it a bit more complicated just to show where we can end up. But really what we can do is log right dot something like this. That's the most basic verification we could do with Moq mock log.verify that log. Now where did log come from? It's just a name we have to give to a variable in a lambda expression. [\[36:38\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2198s) So it could be x, could be y, it doesn't really matter. But this always refers to this. Okay. So verify that the log.Write got called. What if we wanted to use a different argument to say that it got called I don't care with any argument. Then we have an API called it. It and then we can say is or is any is any is the one I use the most. So is any string. [\[37:08\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2228s) And this satisfies the compiler and says I don't care what you got called with as long as it's any string. But I can also say it is or is in a range or is a regular expression. So it is we I can also do a lambda expression here. It is a string that string contains [\[37:40\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2260s) It is a string where s dot contains a I think I'm missing something here. Oh yeah, I know why. It is a string. a. So we have to tell it what is the type [\[38:14\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2294s) And that's basically it. So now it looks a bit more scary actually. Just the fact that the the API exists doesn't mean that we have to use it. What do I have too many of these? >> Semicolon. >> Another one. >> Oh, semicolon. No, there's another one missing. There we go. [\[38:45\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2325s) You see that simple? I love compilers. So we are looking for log right that with a string. And now we would have to do this for any parameter that we care about. So once we choose this, we can say for the second parameter we can say another it is or we can say directly the parameter type whatever we want. But it becomes a bit horrible actually. So sometimes there is a actually a problem with frameworks like this is that the API usage becomes [\[39:22\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2362s) A problem for readability. Let's look at the test with two with two with two dependencies. So now I have a mock of ILogger which is a stub and now we can say stublo log setup. So for the logger x when you say write with any string I want you to throw an exception. [\[39:54\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2394s) When we say mock service we just send it in just like here and then we would verify it against the mock service that got written to. Another option that we can have is we can actually have a virtual method instead of an interface. So we can actually inherit from a class and override a virtual method and then we would have to use a special protected API that says I want you to go through a to protected mode and to set up a special [\[40:26\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2426s) Method. Now because the method is not public we have to use a string. So we can say when write to log is called with yo it becomes verifiable and that's a horrible API but that's the way you do it and then you say verify in the end just like you used to do with NUnit Mocks. So here this is how you would make sure that a protected method called write to log which is virtual got called on a real class. So this is not an interface if you'll notice. [\[40:57\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2457s) Let me just get rid of this inspection options and go away. So the protected API, you actually have to have a special using for it or you won't see it. It's this. If you don't have this using, you're not going to get this protected API. The reason is is that the creator of Moq didn't think it was a it was a great idea to override virtual protective methods. [\[41:27\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2487s) He would rather that you just use public methods. So that's his way of discouraging you from doing that. Okay. And so again it's a design decision. Questions about Moq. So Moq is again w wildly used. Not wildly but widely used. Now let's take a look at the last framework which is proxy based [\[41:57\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2517s) That's called FakeItEasy. FakeItEasy is my current favorite because I really like the API. This is the first test with FakeItEasy and all of these you can install with NuGet if you want. So we create a fake of ILogger. So everything with FakeItEasy begins with the letter a everything. So a fake of ILogger and we get back a fake. [\[42:27\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2547s) Now we want to set up the the behavior. We can say a call to then we have a lambda that doesn't take any arguments. A call to fake.Write with a string that is ignored. throws a new exception. Okay. So now we can actually call login manager with the mock. We can also say a call to fake.Write with a string not m must have happened. [\[42:59\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2579s) Now you usually wouldn't do these two things for the first test. This is just an example of how you set up the behavior. Okay. But this is really how the first test would look with FakeItEasy. you create a fake of ILogger then you ask a call to fake.Write with any string must have happened and if it didn't you get an exception. Now what's also good about FakeItEasy is that the error messages are really good. The error messages in Moq are really not good. They're they're not really helpful unfortunately. [\[43:31\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2611s) And you're going to see that throughout the the day when you start using Moq as well. So you can see that the the design decisions around the API are very different. There's a single point of entry and this is something that also isolator did. So FakeItEasy is a bit later than isolator and I'd like to think that it used the isolator naming convent the isolator API conventions to do this. But regardless I really like this API because isolator doesn't use the the word a [\[44:01\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2641s) Which I actually better I think than how isolated looks. Okay, let's let's move on and see what happens when we're talking about profilerbased frameworks. And at the beginning, you're not going to see any big differences except that with isolator, you have to put isolated attribute at the top of the class. And right now, you you see red here because I don't have a reference to one of the modules, but for demo purposes, it's not necessary. So, you put isolated here. [\[44:32\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2672s) And this is important because without it isolator doesn't clean up fakes between tests and because you can use isolator to fake static things as well then suddenly you can have a test that tells a static method how to behave and then the test next after that might get the same behavior if it didn't clear out before. So this is something that is really important. You can also put it at any method level if you want it. [\[45:03\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2703s) But you're doing this, it's as if you put isolated at the method level. So this is the first test with isolator. Again, the idea is that you have a single entry point. Everything starts with isolated. So isolate.fake.instance of ILogger. You get back a fake logger, which is an ILogger. Then we create a login manager with mock and we initialize it with fake ILogger. What's interesting is that again we don't have a parent. [\[45:35\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2735s) We just directly tell how it's how it's going to behave or verify against the static isolate word. So isolate.verify dot was called with exact arguments. There's also a was called with any arguments. or was called with arguments matching and we have an empty lambda that just say fake ILogger.right with yo. [\[46:06\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2766s) Now there's a big difference in terms of design decisions on what happens when you send in parameters to fake calls here. This is really what's important. If I said was called with exact arguments then this is considered into the asserts. If I said was called with any arguments, this is not considered. I can send in whatever I want because it's just to satisfy the compiler. Here's another example of the design the difference between from all the other frameworks. [\[46:39\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2799s) Here I have a logger and a web service and I want the logger to always throw an exception. So I can say create a fake instance isolate.fake.instance instance of ILogger and I then I say isolate dot when called okay fake logger.Write and I'm actually using the real instance of fake logger when fake logger.Write writes with anything gets called. How do I know it's with anything? Because by default isolator ignores parameters. [\[47:13\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2833s) So I can send in null. I can send in one. By default isolator will assume that I mean anything unless I say dot with exact arguments. So it's the opposite. In all other frameworks by default it takes into account what you're saying unless you say ignored or it is any etc. And the reason is does this is because most of the time you want to you don't care. So we want the test to be as less brittle as possible. [\[47:47\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2867s) So usually we don't care because if suddenly you do care and the input changes suddenly the sets stop work working and you have to change all your expectations all your behavior. So anything really means anything. So it throws an exception on anything from this moment on to the end of time this will always behave this way. But if I had said this was called when called fake logger.Write Right. [\[48:17\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2897s) So if I if I done this dot call original then what's going to happen is that the first time fake logger.Write gets called it's going to throw an exception but on the second time it gets called and from that moment on it's actually going to call the original method we faked. Okay, so I can actually set multiple behaviors just by calling it multiple times. [\[48:50\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2930s) So always the last one is the one that gets considered. If there are multiple they just put in like in a in a queue. Now we have the fake web service and we say new login manager with mock and stop put the web fake web service and the fake logger and isolate.verify verify was called with any arguments fake web service. [\[49:21\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2961s) Okay. So, so far there has been no difference in terms of how you use isolator than all the other proxy based frameworks. So, let's see where this difference actually comes into play. If we look at login manager with statics here we have a more interesting situation. The interesting situation here is that in here is login okay is not really calling an interface. It's calling a static logger class with a static method [\[49:53\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=2993s) And we want to check that it actually gets called. Now because it's static, we can't really replace it because there is no instance to replace. There's nothing to inject. If we were using a proxy based frameworks, we cannot replace it without refactoring the code to make it more testable. What if we don't want to do that or we don't have a way to do that? We're not allowed or it's not our code, etc. So if you wanted to check that static logger.Write write got called with isolator. [\[50:25\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3025s) You would do something like this. You would say create a new login manager with statics, which is the class we just looked at. It's the this one. Sorry, it's this one right here. [\[50:56\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3056s) Create the login manager with static call is login. Okay. And verify was called with any arguments. Static logger. We actually got call it directly. But this wouldn't work without us just telling isolator that we just want to track this static method for later. So we just have to say isolate fake static methods on the type of static clogger. [\[51:28\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3088s) From this moment on all the static methods on this type will get flagged to be noticed later. So now I can actually check. Hold on. I'm going to answer your question. >> You will. Yes, you will answer me. Now, >> by default, this is the preferred way because usually I don't care about all the static methods if I don't care about one of them unless I'm actually testing one of them. But this way if I get new static methods later during in during my other designs next year, [\[51:59\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3119s) My test will actually include those static methods by default. So, I don't have to change my test if I don't want to if I want to ignore them later. So, my test is actually more durable, more maintainable. I could pick and choose. I can say just ignore one single static methods if I wanted to. For example, I can say instead of this I could say isolate when called static logger.Write [\[52:35\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3155s) With anything dot ignore call. From this moment on, this method will do nothing but it will be tracked. So I can actually verify it got called. So now I chose one method. But if tomorrow I'm going to get another method and another method that I'm going to need to to fake, then every time I'm going to need to go back to this test and all the other tests that need to fake it and add those extra methods. Now what's the question? The question was [\[53:07\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3187s) If you want this test in parallel so the isolated u well obviously will create so it's it's a different I injection take taking place because it's when static member would have been messy otherwise so we can so this problem also goes away because currently we obviously we have the problems if we have some static members we avoid them as fast >> you lost me Can you ask? Can you ask? >> Yeah. Yeah. Okay. So I will not get into trouble if I run tests in parallel with that. [\[53:42\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3222s) >> Yes, you will get into trouble >> with that. >> Yes. >> Still okay. >> Because currently as far as far as I remember it's not thread safe, but it is process or app domain safe because there's no problem there. So as long as different instances different app domains but it's not thread safe the different >> that >> yeah the different behaviors. Okay. Any other questions about this? [\[54:15\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3255s) What if I wanted to verify that when static logger write actually throws an exception that it calls static web service. Right? Because we used we actually had that requirement before. I want to I want to I want this to simulate an exception and I want this to verify that it got called. Here's a way to do that. We can fake all the static methods of static logger or all the static meth and all the static meth static web service. We can also say look when when called static logger.Write dot will throw new logger exception. [\[54:49\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3289s) You can see it almost reads like an English sentence. Then we call login manager with statics is login okay and we verify isolate verify was called with any arguments static web service.Write Right. So it's pretty simple without actually changing a piece of code. Okay. We can also get the various parameters. So we can actually say when called static web service write do instead we can actually change the behavior and say we get the context with all the parameters that were sent in and we can say text written to web service and we can actually override things if we wanted to just like registering to an event. [\[55:34\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3334s) But these are more advanced scenarios. We don't have to worry about it right now. Let's take an even more advanced problem. What happens when we have something like this login manager with future object? So now in our code we have a new real logger.Write. Someone is actually saying new relogger. So even if we wanted to it's not static but we don't have a way to inject an instance because it's always creating a new instance. [\[56:08\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3368s) Okay. But we still want to make sure it got called or we want to fake it so that we don't have a dependency problem. the same here. New web service.Write. How do we take care of that? So this is what it would look like. If we wanted to take over a future instance, then we would say we create a fake instance of real logger. And because this is a profiler based, I can create an instance of anything I want. [\[56:42\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3402s) Even if it's a even even if it has a private constructor or it's not an interface really, I can say isolate.fake instance of real logger and that and call it a fake logger. And I want you to isolate. The next instance of this type with my fake logger. So now if I was to say fake logger when called throws an exception and then swap the instance then the next instance of real logger what's going to happen is that the call is going to be redirected to my fake logger and it's actually going to throw an exception. [\[57:22\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3442s) So even if there is a new inside my my method call. Okay. Okay, so now I can also verify it was called verify was called with any arguments my fake logger because it's going to be replaced with the next instance. That's a very powerful feature. But it's not powerful enough because this test will only work for the one next instance. What if I already have a singleton instance somewhere living? How do I replace that? So in that case we can say swap [\[57:55\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3475s) All instances of relogger with the fake logger. So now all future and existing instances will get redirected. Okay. And now that means that if I have a singleton I can just it will behave differently. But if I have a singleton I can also work in a different way. Let's say I have a singleton somewhere that looks like like this. My config settings instance dot [\[58:27\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3507s) Machine name or something like that or username. Okay, now this is really a singleton. If I wanted this is the way a singleton might look like. If I wanted to, I could say isolate when called my config settings instance dot user name [\[59:04\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3544s) Dot will will return Roy. So that will work as well. And the reason it will work is I'm just picking and choosing and actually saying, "Look, I want you to fake all this chain of things." So, they're all going to be fake actually. I want you to fake all the way through my config to my username. And that's actually going to be fake. Another powerful feature of most of these frameworks is that there's the idea of [recursive fakes](https://osherove.com/blog/2008/10/4/isolator-feature-focus-recursive-fakes.html "Isolator feature focus: Recursive Fakes (osherove.com)"). [\[59:39\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3579s) So if I have a fake object and that fake object has a property called person, that person is going to be fake by default as well. If that person has a property of a different person, that property is going to be fake as well. That means that if I have a chain of object that's going to be used inside my code, I just need one line of code to fake the the whole hierarchy. I don't my test will actually be more readable. This is something that Typemock Isolator pioneered [\[1:00:09\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3609s) And the idea of recursive fakes and then other frameworks added that as well. Now with the proxy based frameworks this will only work if the properties are virtual or their interfaces otherwise it cannot fake them. With isolator this will work with anything. So private methods, public methods, static methods if they have a value they return the default value. If they have an object they return a fake. That's what they do by default. Okay. [\[1:00:40\]](https://www.youtube.com/watch?v=rtAlQt2l-0s&t=3640s) So that was the big difference between profilerbased and proxy based frameworks. You can see that the differences in terms of abilities are huge. And what we're going to do now is we're going to do some exercises using Moq and later also isolator and FakeItEasy to actually drive this knowledge into our hands not just our minds. Any questions before we get started? Okay, let's take a 5 minute break for coffee and then we'll do the do the exercises. ## Related - [Constrained and unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1) · The Art of Unit Testing, 2nd ed., ch. 6 The 2nd edition's section on constrained and unconstrained frameworks, the proxy versus profiler split the lesson explains. - [Current isolation frameworks for .NET](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5) · The Art of Unit Testing, 2nd ed., ch. 5 The 2nd edition's survey of current .NET isolation frameworks, the same tools compared on the logger tests. - [Isolation frameworks – lessons from the wild](https://osherove.com/blog/2008/12/3/isolation-frameworks-lessons-from-the-wild.html) · osherove.com Roy's notes from teaching the major .NET isolation frameworks side by side in a master class. - [JustMock and Moles – A short overview for TDD alpha geeks](https://osherove.com/blog/2010/5/25/justmock-and-moles-a-short-overview-for-tdd-alpha-geeks.html) · osherove.com A short overview of JustMock and Moles, two of the profiler-based frameworks named in this lesson. - [Faking static methods in Moq, FakeItEasy and NSubstitute might be closer than imagined](https://osherove.com/blog/2012/7/8/faking-static-methods-in-moq-fakeiteasy-and-nsubstitute-migh.html) · osherove.com On faking static methods with proxy-based frameworks, the limit the lesson contrasts with Isolator. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Defining isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99), ch. 5 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [The importance of differentiating between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_79), ch. 4 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 - [Maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8), ch. 8 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Extracting a common interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74), ch. 3 - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19), ch. 1 #### The Art of Unit Testing, 2nd ed. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Constrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev2sec1), ch. 6 - [First steps with NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3), ch. 2 - [Why use isolation frameworks?](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec1), ch. 5 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 #### osherove.com - [The future of Isolation frameworks, and how Moq isn't it (for now)](https://osherove.com/blog/2012/6/27/the-future-of-isolation-frameworks-and-how-moq-isnt-it-for-n.html) - [FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition?](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html) - [Minimizing unit Test Fragility – 8 features in Typemock Isolator to help](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html) - [Using TypeMock vs. Design for testability](https://osherove.com/blog/2006/9/27/using-typemock-vs-design-for-testability.html) - [Isolator feature focus: Recursive Fakes](https://osherove.com/blog/2008/10/4/isolator-feature-focus-recursive-fakes.html) [Previous lesson Introduction to Hand Written Fakes, Mocks and Stubs](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/introduction-to-hand-written-fakes-mocks-and-stubs/) [Next lesson Test Review Practices](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-review-practices/) --- title: "Test Review Practices" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-review-practices.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-review-practices/" tags: [] author: "Roy Osherove" description: "Lesson 6 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Test Review Insights), 1:00:31. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Test Review Practices 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 3. Test Review Insights Lesson 6 of 14 Duration: 1:00:31 [Watch on YouTube](https://www.youtube.com/watch?v=Zc0eJXNKfdw) Roy explains what to look for when [reviewing other people's tests](https://www.artofunittesting.com/unit-testing-review-guidelines "Test Review Guidelines (artofunittesting.com)") ## In this lesson Roy Osherove explains that [test reviews](https://osherove.com/videos/2011/2/6/how-to-do-test-reviews.html "How to do test reviews (osherove.com)") spread knowledge and that reviews starting from the tests are shorter because tests show the developer's intent, and names [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)"), [maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)") and [trustworthiness](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7 "Trustworthy tests (The Art of Unit Testing, 3rd ed., ch. 7)") as the [pillars of good tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8 "The pillars of good unit tests (The Art of Unit Testing, 2nd ed., ch. 8)"). In tests from [NerdDinner](https://osherove.com/blog/2009/3/20/test-review-1-nerddinner.html "Test Review #1 - NerdDinner (osherove.com)"), [ASP.NET MVC](https://osherove.com/blog/2009/3/21/test-review-2-aspnet-mvc-unit-tests.html "Test Review #2 – ASP.NET MVC Unit Tests (osherove.com)") and other projects he points out logic, [magic numbers](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_169 "Magic values and naming variables (The Art of Unit Testing, 3rd ed., ch. 9)"), [dynamically built expected values](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_142 "Logic in asserts: Creating dynamic expected values (The Art of Unit Testing, 3rd ed., ch. 7)") and [several tests in one method](https://osherove.com/blog/2011/2/9/multiple-mocks-asserts-and-hidden-results.html "Multiple mocks, asserts, and hidden results (osherove.com)"). He also warns against [over-specified mocks](https://osherove.com/blog/2008/7/12/over-specification-in-tests.html "Over Specification in Tests (osherove.com)") that should be [stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)"), allows [at most one mock per test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec5 "One mock per test (The Art of Unit Testing, 2nd ed., ch. 4)"), and breaks production code by hand in reviews to see whether a test fails. ## Transcript 9,124 words [\[00:24\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=24s) Okay, let's continue. I want to talk about a bit more formally about [test reviews](https://osherove.com/blog/2007/3/13/test-reviews-vs-code-reviews-some-helpful-tips.html "Test Reviews Vs. Code Reviews - Some Helpful Tips (osherove.com)") and things to look for because what we've done so far is we've looked at test and randomly I said things but there is a there is a system to the whole idea there is a list of things that I look for so first we're going to talk about test reviews and [\[00:54\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=54s) Then the [three pillars](https://osherove.com/blog/2012/9/17/readable-maintainable-trustworthy-unit-tests-in-java.html "Readable, Maintainable, Trustworthy Unit Tests in Java (osherove.com)") of what to me make good tests. The first thing to understand is that test reviews are one of the most effective ways that you will have to spread knowledge in your organization and to help [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") actually be adopted in your organization. So if you if you want to have any hope whatsoever of having unit testing adopted, [\[01:26\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=86s) You're going to have to learn and actually do test reviews in your organization. And the reason is is that there is nothing better than simple face-to-face human communication sitting down in front of the same code and finding interesting things and how to make them even better. test reviews. But there's also a benefit to doing test reviews versus just regular code reviews. If you start code reviews from the tests, [\[01:58\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=118s) The main benefit you're going to get is that your reviews will usually be shorter, sometimes up to 10 times. The main reason is that when you have tests, then the test itself reveals the intent of what the developer was trying to do. When you look at code, you don't see intent. you have to read a bunch of lines of code to understand the intent. So in real code, sometimes you're going to have to read 20, 30, 50 lines just to understand that they're doing the wrong thing that they got the requirement wrong. [\[02:29\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=149s) Sometimes when you look at it, so you might say you go to the end of the method and then you say, "Oh, so you delete the object from the database only when this is true." But it takes time to understand this. When you sometimes by just looking at the name of the test, you realize that something that there was a misunderstanding even before looking at a single line of code. So test reviews are a good way to understand the intent of developers and they're a good way to drill down into code [\[03:02\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=182s) When you want to review how things actually got done. So you see what the developer tried to do. Then you could drill down from the method which is a test to see how it actually got implemented. The three main pillars of good tests are [readability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec3 "Writing readable tests (The Art of Unit Testing, 2nd ed., ch. 8)"), [maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec2 "Writing maintainable tests (The Art of Unit Testing, 2nd ed., ch. 8)") and [trustworthiness](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec1 "Writing trustworthy tests (The Art of Unit Testing, 2nd ed., ch. 8)"). If you even lose one of them then you're then the rest will break. Why do we need readability? What's the point of readability? [\[03:33\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=213s) What do we get? >> Nothing. >> A quicker view of what's happening. >> It allows us to do review quicker. It allows us to understand why a test is failing when it's failing. So, it will allow us to find the bugs faster. What about maintainability? What's a maintainability in a test? What does it mean? Yeah. Yeah. Well, if we leave if we change a structure of the code that they that's easy to to to maintain the test as well. [\[04:06\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=246s) So we don't have so so it's it's not a complicated structure that we have to mess around a lot with. So it's easy to to change. So if we change the structure of the code, the code becomes easier to change. The the tests are actually easier to change than if we weren't keeping them attainable. In fact this is one of the biggest problems with tests is that they add extra maintainability cost to our code. So the maintainability aspect is one of the things we have to worry about a lot in terms of tests even more so than regular code because in regular code we might have [\[04:42\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=282s) We might have one thing but in test a you might have multiple tests for that one thing. So this is actually you actually have a shotgun effect that when you change that one thing you actually get to maintain five or more different other tests. Trustworthiness is the the one thing that it's always the hardest to explain but the way I think about trustworthiness is what happens when you see the test result of a of a passing test. [\[05:16\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=316s) Do you still feel the need to debug the test? If you do, then you don't really [trust](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134 "How to know you trust a test (The Art of Unit Testing, 3rd ed., ch. 7)") the result and it's not really saving you any time. Also, trust is when tests can lie to you and they say that they fail for the wrong reason. So that you stop believing the tests because the result that you get is not the result that should have been. You know the test should pass and it fails and you know that it's a configuration issue. And this is a problem because when we stop believing our test then again we're not really saving any time by listening to them. [\[05:52\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=352s) So we don't really know that things are broken or not. We have to go and find out for ourselves. Now if we lose trust then then we won't care about the readability or maintainability of the test. We just won't run them or we won't change them when they start failing. If we lose readability, we won't be able to maintain the tests and then eventually we won't trust them. If we can't maintain the tests, it's just a matter of time until we stop using them altogether. One of my first projects ever was [\[06:23\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=383s) A project where about six months into the project or eight months, I don't remember exactly, we had to stop working on the test. We had to actually delete some of them, a lot of them, about half because they kept failing and we didn't have time to keep fixing them and that's where the maintainability really came in. And so all that time we spent writing them and learning how to write them etc. it actually just we actually threw it in the garbage. So we don't want to go through that again. [\[06:56\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=416s) So one of the things that I already said is that in terms of readability and trust we want to make the tests easy to run and we want to separate the unit tests from [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)"). Now here in this structure this is the [NerdDinner](https://osherove.com/blog/2009/3/20/test-review-1-nerddinner.html "Test Review #1 - NerdDinner (osherove.com)") tests and there's only one project that contains test. So there's no separation between unit and integration and that's one of the easiest thing to things to fix. But also when I look at tests, I look at the structure and I look at the fact that we have [fakes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") and models and controllers [\[07:33\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=453s) And and what I'm looking for is if I look at the piece of code of production code, is it easy for me to find the test for that production code? That's my that's my test for readability. Is it is the structure readable? Is it easy to find one thing from another? And it should be. So usually we would have a project of tests or unit test per per project of production code. We would have at the very beginning a a cla a test class per production class. [\[08:05\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=485s) If we wanted to, we could we could have different matchings, but this is the easiest way to find things that match each other. And if we had a problem with how it's organized later, we can reorganize. But at the beginning this really helps to trust your tests and to get better understanding of how it works. [Code coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)") is actually important but it's only important in specific levels. [\[08:36\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=516s) So my question is if you have 99 or 100% code coverage, what does that mean? Does it mean anything? >> Well, you at least have a test that in some condition passed the code line. >> Sorry. You have you have enough tests to to to pass that code line in in one condition. You have enough tests that run that don't break. [\[09:07\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=547s) That's all it means. It doesn't mean that anything works. It just mean that nothing is throwing exceptions. If we have a 100% test coverage, it doesn't mean anything unless we review the tests and we know that they're good. For example, we can have all the tests without asserting them, but we can still have 100% code coverage. So code coverage, which is high, doesn't mean anything without a review. What about 12% code coverage? Does that many mean anything? [\[09:45\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=585s) If I have 12% code coverage, what does that mean? >> So the classes are not tested. >> It means that I'm missing tests. It definitely means something. If it's high, it doesn't mean anything. Unless I review the code in the tests. If it's low, it definitely means something that I'm missing tests. That's what test coverage helps. But I use code coverage or test coverage also for a couple of other reasons. [\[10:15\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=615s) When I review other people's tests and code, I like to sometimes change things manually. I look at the specific test and I'm not sure whether I trust it or not. So, I go to the code that's kind of under the test and I physically change something in the code. I'll take a true and turn it into a false. I'll take an if and I'll make it always true or something like that. Now if I do that which is an obvious bug in the system what's what should happen one test should break somewhere >> at least one test somewhere has to break but if nothing breaks what does that mean [\[10:53\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=653s) Tested >> means it's not really being tested or the test that we think is okay is not really okay now the reason I do this manually is is about communication I sit down with a person they can see my face they can see me talking and thinking out loud and then trying this. And also when I do this, I ask them, "What do you think? Is anything going to break?" And just by looking at their face before they answer, I can tell if they wrote it in a [test-driven](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") way or not. Because if you wrote it in a test-driven way, you're absolutely going to be sure that there's something going to break. [\[11:27\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=687s) Yeah, totally going to break. Yeah, I know it. Because they know that that code had a reason to live because they wrote it only after something broke. If they didn't, they're going to have a lot of question marks on their faces. Maybe. I'm not sure. I think so. And so it's a good way to tell what is the culture. How sure are people about their code and their tests? It's not about punishment. It's about communication. It's about seeing how people react to that situation. [\[12:03\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=723s) Another thing that we want in our test is to prevent logic. Logic is also a trust issue. The reason is that logic can lead to bugs in our tests. So we want our test to have as little logic as possible. Where's the logic in this test? Is there logic here? There is. Logic is anything that's an if or a switch or a loop. [\[12:34\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=754s) Anything that that can change the course of of work. So here's the logic right here. And what's interesting is that there are many other things wrong with this test. But for now, what jumps out to me is the fact that there is a loop right there at the bottom. So let's try and understand this test a little better. Let's look at the name. Select constructor with two parameters. [\[13:10\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=790s) U okay. Is this a good name or not? Not a good name. Why? What's missing? The [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") >> the unit the unit of work is missing. >> Well, the unit of work in this case is actually select constructor. So, it's not missing. Okay. What's in there? Select constructor >> behavior. >> The behavior is missing, but we do have the scenario with two parameters. So, [\[13:41\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=821s) You're the reader of the test. You say okay selective structure with two parameters that's good. What's supposed to happen? And now the problem is that we have multiple things being tested as the thing that's supposed to happen. So which one of them is the important one? Because if we look at the bottom we have we're getting we have asserts here in the middle assert are equal for the constructor and assert that we get two parameter keys. Which one of them is the important one? Are they both the important one? [\[14:12\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=852s) What about this? Then we have a loop for each key in keys assert that the policy is correct for the key whatever that means. So is the bottom loop the important one or the the first assert the important one because if they are both important then they should be separated into two different tests. And the big reason is that if the asserts at the top break then the asserts at the bottom will never get executed. However, if all of these are just the asserts on the same thing, [\[14:47\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=887s) Then we don't care about the asserts at the bottom if the first one's right. And for that, we would have to know the domain. We need to know in the domain what what's important, what's not important. But the fact that there are [multiple asserts](https://osherove.com/blog/2005/4/14/try-to-avoid-multiple-asserts-in-a-single-unit-test.html "Try to avoid multiple asserts in a single unit test (osherove.com)") that can break each other that can break and then we won't know what's going on at the bottom actually tells me that I think that the that this should be separated into two different tests. If the [test name](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html "Naming standards for unit tests (osherove.com)") had told me what's the expected one then I would know but one of the reasons the test doesn't tell me I could guess is because the test is testing more than a single thing and so the name has to be more generic. [\[15:27\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=927s) Okay, if all these things have to be true, then they should be separated. But there are also some things that repeat themselves. We're asserting if we get back to here and then we asserting we get back to here. It's the same thing. This is selected ctor. This is selected ctor. >> How could this be that the same assert is repeated twice in the same test? Any ideas? Yeah, they're coming in. [\[15:58\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=958s) They merge two tests to one or something. They merge two tests into one test. Interesting. That's possible. So, two different people. And again, this is something that a test reviewer would catch immediately. So many questions just reading the test. A test should not leave you with questions. It should leave you with answers. And if you leave the test asking more questions about what the hell is going on here, maybe maybe that's a good thing because you need to learn things. [\[16:30\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=990s) But if no test give you answers gives you good answers, then you're stuck. Okay, so how do I get rid of the loop? Well, first of all, if I know I have two keys, I don't need to loop. I can just have two statements to check each one of these. Second of all, maybe I don't need to look to check assert on the both of them. Maybe checking just on the first one is good enough. [\[17:01\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1021s) If checking on the second one is a separate concern, then maybe I should have a separate test that proves that if I have multiple, then the the last one also gets gets a good assert policy because if a single if a single key proves my point, I don't need to use two keys. And that's another important thing about unit tests. If you can simplify them and use less things in the test, then do that. If you can prove this test with just a single parameter instead of two and it proves the same thing, then do that. [\[17:36\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1056s) A lot of times people complicate the test just to get a sense of more confidence. That's not a bad thing. But then I would put all these tests in a special class called confidence boosting tests or something like that or experiments. And the reason is that if I look at the class, I then know that these tests don't really have the same rules as the other tests. The whole point of these other tests is to just feel more confident. Like what happens if I now have 17 parameters and three different flags and all that stuff? [\[18:09\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1089s) And the point of those tests is to boost confidence. There's nothing wrong with that as long as you make your intent clear. What about other things in this test? Are you happy with this test otherwise? Is it okay? Yeah. The one thing is the act is just a select constructor line and it's not separated from it. So it's it so we have the assert as if I see C would be the first three statements and then we have the act separate it actually looks like it belongs to the other block. [\[18:42\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1122s) It was a bit confusing. >> So I didn't understand you're saying that the act assert or arrange is just broken here. >> Yes. Visually. >> Yeah. Visually we have assert and then another act and then another assert. Are you sure? >> No. We have if I understand correctly the first three lines constructor info specified builder context are a range the next is the act and that is not visually clear. >> So the first two parts you're not sure where what's the act and what's the arrange [\[19:13\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1153s) >> yeah is well it's usually the last line before the first assert that's the the act part >> usually. Yeah but yeah I wish I had that problem only that problem in the test. What else? >> It's a [magic number](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_169 "Magic values and naming variables (The Art of Unit Testing, 3rd ed., ch. 9)"). >> Magic number. 37. >> Yeah, 37 is definitely a magic number. How do I find out what it means? I now have to look like finding files throughout the solution. Where does 37 come from? And maybe I'll never find it. Maybe 37 is the number of methods in a specific class. [\[19:47\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1187s) Maybe it's the number of files in a specific folder. Maybe it's the number of seconds that have to go before a specific thread somewhere actually gets released. We might never find out. And that's a horrible, horrible problem. So no magic number. If 37 doesn't matter, just put it in a const and be done with it. ABC is kind of okay because ABC looks like nothing. [\[20:19\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1219s) Okay, here's another example of logic. In our test, a lot of times we would have fake classes that implement various parameters, right? So, if we have fake classes that implement various interfaces, etc. We don't want to have logic in them as well. But here is an example of one of them that has logic. You see the epher here below. So sometimes the object will behave in a specific way and sometimes it will will behave differently. [\[20:52\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1252s) Now our test might be using this and since this is not part of the test, it has it's located somewhere else. What's going to happen is that our test is going to behave in a specific way and we won't know why. We're going to have to drill down and understand why and start debugging instead of reading what how it's supposed to behave. So to avoid this, I would tell from the test how everything will behave. Just like in previous lessons, we've learned that when you when you have a behavior like throwing an exception, your test should be specific about telling you that the exception will be thrown from a specific fake object. [\[21:30\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1290s) It's not supposed to be magical. Also configuration interface is assignable from is an in a reflection method that is very very confusing. If you ever used this method in reflection net before can tell you that you always use it the opposite of how it's supposed to be used. You always think that you're supposed to send in specific type and it's the opposite of the type that you're trying to get because I try to use it. So you can actually have a bug in this piece of logic which is part of the tests and so your test will behave in in a in a in an interesting way and you won't understand that you even have a bug because you don't have tests for this code. [\[22:12\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1332s) And that's one of the reasons you want to avoid logic. Even if you think you're okay, you can have a serious bug here where you return false instead of null or whatever. Here's another example of things that could be related to logic. This is another [helper method](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6 "Building a test API for your application (The Art of Unit Testing, 2nd ed., ch. 7)") in tests from [ASP.NET MVC](https://osherove.com/blog/2009/3/21/test-review-2-aspnet-mvc-unit-tests.html "Test Review #2 – ASP.NET MVC Unit Tests (osherove.com)"). And this is a method that creates a fake HTTP context. So we can see that it has the app path and various other parameters. [\[22:44\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1364s) And then it has a check. If we have an app path, then create a fake application path. If we have a request path then check and replace the app relative current blah blah blah blah. If we have a port then create the URI this way otherwise create URI that way and then set the URI to whatever and then the HTTP context will behave in a fake way. But the problem again is that not only is this almost unreadable, [\[23:15\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1395s) It's also prone to errors. So we want to avoid errors over time. This is prone to a lot of errors. Even though the ifs look simple even simple stuff we can have bugs in. So now we have a lot of we might have tested that that created HTTP context. And the HTTP context might behave badly. And you don't look at the helper methods to understand why bugs happen because that's usually the last place you look at. [\[23:48\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1428s) How can we avoid all these ifs? Any ideas? >> Test. >> So, this is not a test. >> It's not a test. >> No, this is just a utility method in the tests. How can we avoid multiple ifs? You're on the right track though. Yeah, >> you set up directly in the tests and not reuse it in this helper method. Well, you can set it up directly in the test, but a utility method does make sense because you keep you could you go repeat the five lines of code every time. [\[24:20\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1460s) But instead of having all these if we can have various versions of the same utility method. So we can have multiple utility method that says for example get HTTP context with app path get HTTP context with request get HTTP context with port and if it didn't have a port then it will they wouldn't have an if because by the fact that they're named a specific way they will always be expect to have an app path or they will actually break. [\[24:52\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1492s) Now I looked and the amount of tests that use this are exactly two by the way. So it's also a symbol of overengineering. Here's an example of trust where you connect. We actually have logic that you assert against. So here the assert at the bottom is asserting that a specific string the expected string is built dynamically. [\[25:22\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1522s) That means that we can actually have a bug with the plus there. Now, usually what happens is that when you [build the expected value dynamically](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_142 "Logic in asserts: Creating dynamic expected values (The Art of Unit Testing, 3rd ed., ch. 7)"), you more likely to be repeating production code. It's more very likely production code has kind of the same code in there. So, if the production code has a bug and you're repeating the same production code, you have a [bug in the test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11 "How can we know we don’t have bugs in our tests? (The Art of Unit Testing, 3rd ed., ch. 11)") as well. And so you expect the bad result in the test. The test will actually pass when it should have failed. [\[25:55\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1555s) So it's much better to use hard-coded values and strings in the test than to generate them dynamically. You're less likely to have bugs and it's also much more readable. Okay, so we this is a previous example of the NerdDinner test. This is an example where we had many more magic stuff like the event date was time now ScottGu was hosted by instead of some user etc. [\[26:32\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1592s) But there are other things wrong with this test. Let's look at the name. Dinner should be valid when all properties are correct. And then we have in the act we have is valid and then we assert that it's true. So what's wrong with that? [\[27:08\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1628s) It's great. It's amazing. Well, what's wrong is that we are the the test is when all properties are correct. Are these all the properties? What does correct mean for each one of them? Is the correct title mean that it has to have a space inside it? Is it the minimum number of characters? What is the correct event date? What's the minimum event date hosted by? Does it have to start with Scott? Country has to be USA. contact phone has to have two dashes inside it. [\[27:40\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1660s) We don't know what does it mean to be valid. And also this test because it's checking so many things. It's the name is very very generic. And every time we add a new property, we're going to have to add it to here and we're going to forget to do that of course. So it's much better to have separate tests for each of the properties in terms of validity. Yes. So that would mean that in your your opinion we should repeat every single validation logic line in a separate test. [\[28:14\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1694s) >> you should repeat every logic line in a separate test. >> Validation logic. >> you should have a good name that explains what it is that you're testing for each piece of validation logic. If you don't have a good name that explains why it fails, how do you know how to fix it? That's my problem. My problem is that I don't know what's valid and what's not. So I need to find a way to do that. And also there are more things here. If this test fails, how do I know which one of them was the invalid one? [\[28:46\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1726s) >> I just try to to think of reality and not this seminar here. And we >> I don't know projects that you have done. So say you have 5,000 6,000 validation rules after a while if you have hundreds of objects or whatever. >> Mhm. So you would whether make one test per per validation rule. So say we have a and I just fix a couple of validation rules before we started today and that would mean so for every single validation rule we get individual tests hopefully more than one because validation rules can will have a true and a false result usually more than a single false result more than a single true result. [\[29:27\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1767s) So if you really want it to work, you're probably going to have to test it multiple ways for each validation rule. Otherwise, it's not that important to you, right? The whole point of a validation rule is that it validates something. Well, how do you know? And validation by by by by nature is a piece of logic. You're going to have to test it multiple ways from Sunday basically. So yeah, it should have a separate test at least one. How do I know it's never, you know, that it always returns valid? Maybe how do I know that it has to return nonvalue at some point right? [\[30:01\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1801s) >> Yeah. >> So I do know that this question will be raised and that's why I don't have an answer for that. No >> what was what do you mean you don't have an answer? >> Yeah. How to to make this in any fashion in any productive fashion but that is one of the main criticisms if I if I start having so I have say one piece of validation logic for one entity say it's about 35 lines of code we talking about well at least 10 times the amount of tests for that for stuff that is built in in the framework the validation itself is just using stuff that is built using attributes So I'm checking all this stuff again and >> I'm not talking about attributes here. [\[30:46\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1846s) I'm talking about pieces of logic that you want to test. >> Yeah, good. >> Okay. So if you wrote custom code with logic for it, you have to test it. You're not supposed to test the framework. But for validation, you this want to prove that no one deleted the attribute, right? You want to make sure I get your point. Now, a lot of times what you're going to get is one big validation method that checks 70 different things. And so in your test, what you're going to have to do is for each one of the validations, you're going to have to simulate that all the other validations are actually okay, [\[31:25\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1885s) Right? And then only the code that validates a specific rule that you want, you want to test that. And one of the ways to do that is with extract an override the way we talked about before is that each one of the validations is actually its own virtual method and we have an override for them and then we can just set flags to return true or false true false whatever we want except the method that's under test and that way we can check a specific piece of validation logic even if it's hidden and buried inside one big method. [\[32:00\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1920s) But it's much better to have separate classes for each validation rule because then you can test them separately. Okay. But in terms of [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)"), extraction override is great for that kind of stuff. If you're writing new code, write a separate class or a separate method that doesn't depend on anything and test that directly with as a validation rule. Okay. [\[32:31\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1951s) >> It doesn't look like you got your answer actually. No, >> no, I got I got my answer. Just the same answer I had before I came here. And that's so yeah, my opinion hasn't changed that. Okay. >> So, what's your opinion? I don't understand. Your opinion is that there's a problem somewhere. >> There definitely a couple of problems in terms of the ratio between effort and what I get for it. Whatever. I don't have to repeat your opinion. I know this already. So the problem is still I have to sell this to people and I still >> So so your problem is selling this to people. Do you believe that it's a good idea though? [\[33:03\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=1983s) >> Not yet. >> Not yet. Okay. So you're going to have to try it and see because usually what you do it takes about five or 10 seconds to create a test for that kind of stuff. So the cost is actually not that big. And the only way to test it without an integration test is to test it separately. And if you're going to use an integration test, it's kind of going to look like this where you don't know what's supposed to be wrong. And if one of them fails, then maybe you won't know about the others that failed. Maybe you will depends on the validation structure, etc. [\[33:35\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2015s) Should >> so what you're saying here is instead of doing it like this it would in the titles set method you you call validate title method instead and test build test method instead. >> Yeah. So your question if I would instead of writing the title here I would I would call a validate title method. Yes, >> I would call a validate title method and I would have val different tests for it like validate title that's empty should actually return false. [\[34:12\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2052s) Validate title bigger than X character to return false etc. I would have one one or two true cases and most of the time I'm looking for a lot of false cases in the validation. Okay, other questions. >> I'm still amused about the latitude. >> Oh, latitude. >> It's way beyond the North Pole. >> we're pretty close to the North Pole right now, aren't we? [\[34:43\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2083s) Feels like it. >> We're about 60 latitude of 60. >> Okay. >> And the North Pole is latitude of 90. >> Yeah. So, >> so just 30. >> It's just 30. >> Just two. >> Two/3. That's very close to me. >> okay. So, this is the same example as a piece of logic that we assert against. What about this? This is an example [\[35:14\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2114s) Of multiple asserts. Okay. Can you tell? So, I didn't even have room to put all at the beginning of the test, but this is one test method. And what it does is that it creates an array. [\[35:47\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2147s) So, there's an array of stuff here. A and each item in the array is an anonymous object that has two properties. One is a property name parameter. Notice how they all have the same name and one is an action which is really an a lambda or a delegate that invokes a specific overload of HTML route link. So there this is a call to a different HTML route link etc etc [\[36:19\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2179s) And the difference between so in the array we have multiple delegates each one of them calling a different version a different overload of HTML helpper.outlink route link and then here at the bottom we have a loop that goes through each one of them and uses exception helper expect argument exception null or empty. Okay. Now what this means what is exception helper? This is using MSTest. [\[36:50\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2210s) MSTest doesn't have assert throws like [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)") although it takes about five lines of code to create it. So this team who wrote this created an exception helper that does exactly what assert throws does. So this is why it uses that. So it goes through each one of the items in the array and then asserts that it throws an error or in terms of readability I'm not sure. It might assert that it's not throwing an error. [\[37:20\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2240s) So, I'm not sure if it means you expect an argument exception that is null or empty or you expect an exception of an argument null or empty. Okay, so it's kind of a problem in terms of readability. I'm not sure. And this is exactly the opposites. I'm not sure if you expect an exception or expect no exception here. That's a problem. But usually when people would use exception helpers is that they expect throws. [\[37:51\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2271s) So I'm assuming they're expecting exceptions for So what's the problem with this? Is this a good test? >> Isn't it basically lots of tests in the same test? >> Yes, it's multiple tests in the same test method. So what's the problem? If it fails, do you really know which other tests that fail? >> If it fails, you don't know which one of them failed. Yes. What else? [\[38:33\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2313s) If it fails in the middle, everything after the middle will never get executed. The loop is going to break, right? because there is no try catch inside the loop here. So if the exception helper throws an exception because it fails the test fails and so maybe the bottom three overloads never get executed and this is an example of a case where you do care about each one of them separately because each one of them is a separate overload is a separate method actually. [\[39:03\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2343s) Okay. So yes, you do need a separate test for each one of them or at the very least you have to fix the loop so that it doesn't break at the test and then you have to log everything that failed when the test finally does fail. So you have to build some infrastructure in this loop and loop by definition are a piece of logic. They can actually have a bug etc etc. So the simpler case would just be a separate test case for each one of them. Yes, >> one question. So [\[39:35\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2375s) Hopefully I will never create lots of frameworks with with multiple overloads because it's it creates this problem. So I have a lot of different overload that I have to check but also when I go back if I understand correctly and I would check the individual the individual values. So all the different version have to be checked. So I get lots and lots of tests for that. Is that correct? Would you do this? >> Well, in this case, I I says it really depends on the domain. [\[40:08\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2408s) What's important, what's not. Let's assume that these are the important tests. So, whatever they test is what I would test. It's separate tests. Okay? Maybe for this domain, it would make sense to also add a couple of more tests. Maybe not. It really does depend on the domain. Okay? So whether I would have multiple tests with different inputs to different parameters for each overload or not really I don't know. If I knew the domain I would know. [\[40:43\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2443s) Here's an example of something that this is this is an example of oversp specification. Now there are multiple things wrong in this test. Let's start with trying to understand what's going on here. So let's look at the name of the tests. Does anyone care to read the name? [\[41:19\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2479s) Invoke action throws if begin invoke action method throws thread abort exception. Now you should say that five times fast. This is where the underscores start to make sense. Which where does something start and something end? It's really hard to read that. So invoke action throws. Now it throws when when beginning invoke action throws something else. So we are expecting at the end to expect an exception [\[41:50\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2510s) And there is this one here. So this is the name tells us this is this is the important part but then if I look at the end of the method there's something interesting going on here mockhelper.verify verify what is [mock](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") helper all these things. Okay, so all these things are a usage of [Moq](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5 "Current isolation frameworks for .NET (The Art of Unit Testing, 2nd ed., ch. 5)") and expect is [\[42:21\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2541s) The previous version of [setup method](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162 "Avoid setup methods (The Art of Unit Testing, 3rd ed., ch. 8)") if you've if you've seen it before and basically it looks at everything that's verifiable and if I set verifiable when I call verify at the end then verify will go through all the verifiables and make sure that they're called. Okay, so really I have 1 2 3 4 five probably six asserts in this single verify. And the funny thing is is that I shouldn't even care because this is what I care about. [\[42:55\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2575s) This is the expected [end result](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)") is that I get back an exception. So the big question is why do I have both an [expected exception](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "Checking for expected thrown errors (The Art of Unit Testing, 3rd ed., ch. 2)") and the verify in this method? What's the basic idea? Well, there is no good reason. The only good reason that used to be is that people would, including me, would verify all the interactions just because they could. That used to be the norm. So, I used to I remember writing tests where at the [tear down](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_171 "Setting up and tearing down (The Art of Unit Testing, 3rd ed., ch. 9)") method, at the end of each test, I would also verify all the interactions just just to make sure. [\[43:37\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2617s) There was something about that. You felt like you had power to do that. But the problem is that you're really cementing all the internal implementation that you have over here. This is all internal implementation. This is all really [stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1 "Introducing stubs (The Art of Unit Testing, 2nd ed., ch. 3)") that return specific results so that I can test whatever it is that I'm testing. And this is kind of like me sending my kid out to get pizza and telling him, "Look, I want when you get back, I need a pizza that looks like this." And then when the kid comes back with the pizza, not only do I verify the pizza, I also pick up the phone and I call the the guy at the pizza store and ask, "Hey, did a come kid come by? [\[44:23\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2663s) Did he pay you exactly this amount of money? Did he say exactly these specific words? Did he did he arrive? Did he put the right foot first when he got got in through the door or the left foot? Because it would have been the right foot. And if the guy said, "Look, he was the left foot." I would throw the pizza out to the garbage because that wasn't what I said would be. And that's exactly what's happening here. If tomorrow the internal implementation of the method would change, [\[44:57\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2697s) As long as I still got the expected exception at the end, what do I care, right? The method, the application still works. I shouldn't care about this. But in fact, this test is the strictest test I could ever I could ever see. Because it it says that every method has to be called. And you know what happens if it had if if a method gets called twice instead? Test will break. It's going to say, "Uh-uh, you said it's going to be called once." [\[45:32\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2732s) So this is an example of what's called oversp specification where you have tests that verify internal implementation instead of just the expected end result. Okay, there are two problems here. One is that I shouldn't have a mock object anyway. It just stubs. And while I have the mock object, I shouldn't be verifying multiple things on it [\[46:07\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2767s) Okay, here's another example of a test. This is a different test, although it's hard to see. Execute core with a synchronous invoker and action completes successfully. What does complete successfully mean? Complete successful. What does that mean? What do you think it means? >> Didn't fail. >> It didn't fail. No exception. Okay. So, it's not it's not expecting any exception. [\[46:39\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2799s) Why do I have two mock objects right here? What the hell is going on here? Well, it's the same as before. We verify just because we can. But there's a different problem here. Here we have two mock objects in a single test. And the test should have no more than a single mock object because every mock object is testing a specific thing. So at the very least, one of them is either unnecessary or has to be used in a separate test. [\[47:09\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2829s) Because if the first one verify it fails, we'll never know if the second one fails in this test. But do we even need both of them? Based on the name of the test, we don't. Based on the name of the test, we just are expecting no exception. Okay. Now, even from the name of the mock objects, I can see and I I can see that one is called mock temp data provider. What is provider? Provider means that the direction of the information is internal. [\[47:40\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2860s) It's into the application. It's not external. It's something that provides information into the application. When I see the word provider, I'm thinking stub because I'm going to use it to create fake data so I can test my application. This is probably not supposed to be a mock object, but people verified because they can because that used to be the norm. What about the second one? Mock invoker. Where does this get used? [\[48:13\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2893s) So we have expect here begin invoke action and then it returns something then end invoke action returns true. So this is again a stub it returns something into the application but we don't need to verify that it was called. We just need to say if this returns true and it returns whatever we need then do we get back no exception execute with the synchronous and action complete successfully. [\[48:45\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2925s) Now the problem is is that we're verifying that it got called. A better way to check that it actually got called or that it actually works is that the asynchronous action actually does something would be a much better way to get a real value that went through the system as it worked. Okay. But this is an example where people didn't know what to test for, so they used a mock object. [\[49:18\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2958s) But again you were verifying that begin invoke and end invoke action got called when in fact you shouldn't be doing that. You should just assume that whatever is execute core where is execute core execute core is this. You should assume that begin execute core does whatever it needs and if it does the work then you should get back some kind of value from it. That would be a better way, a statebased test that you get back a return value or that something in the system changes. [\[49:50\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=2990s) I wouldn't use a mock object here, but just stubs and then check a value that I can do something in the synchronous action like set a variable locally and then see that it actually got set. Okay, right now all it proves is that it calls the begin stuff and end stuff, but it doesn't prove that it does anything. And I want to prove that he did anything. If my kid came back with a pizza, I wouldn't even look at the pizza. I would just call the delivery guy or the the pizza guy and and that's how and that's how I would become [\[50:26\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3026s) Less hungry if he told me that my kid bought the pizza. That doesn't make sense. I need to eat the pizza. Okay, I'm not just saying that because we're just before lunch and I'm hungry. Okay, but this is an example of a test that says what's really important to me is that you called this. I don't care if it actually got something back or that you did anything. I just care that you called someone. And I've seen a lot of tests like this where people verify that some virtual method got called [\[50:58\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3058s) Or verify that some base class method got called instead of verifying the actual action. And when you can verify an actual action, it's much better than verifying an interaction. So I would go for so far as saying that mock objects or [interaction tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec1 "Value-based vs. state-based vs. interaction testing (The Art of Unit Testing, 2nd ed., ch. 4)") should be no more than maybe 5% of your projects of your code. They should be not the norm. They should be the exception of having mock objects in your tests because they're harder to read. And they are and they don't tell you what really happened. [\[51:30\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3090s) They just tell you that something got called. Sometimes that's the only thing you can do, but sometimes not. And whenever you can do something different, you should do that. Okay. This is an example of another antiattern that I can see in a lot of tests in terms of readability. and maintainability [\[52:02\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3122s) Where people will create at the top you can see how people will create a chain of objects. So you have a mock principle which is really a fake principle that returns a fake identity. It returns a fake identity here. So that's how people might return a chain of fake objects. But all the latest frameworks including Moq, Rhino and isolator have introduced the idea of [recursive fakes](https://osherove.com/blog/2008/10/4/isolator-feature-focus-recursive-fakes.html "Isolator feature focus: Recursive Fakes (osherove.com)") where you can create an instance of IPrincipal [\[52:35\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3155s) And principle.identity will already be fake in the single line of code. So every property that is an object of a fake object will be a fake object and every property that is a a value object will have a default value. So we shouldn't do hard-coded chains in code anymore. We can just use the frameworks to give us that extra edge in terms of readability and maintainability in the tests because what happens if someone now uses the identity do something in our tests? [\[53:09\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3189s) Now, we have to go and add another line of code. If we were doing it the the way we did, the upper way to to all the tests that that use this, that's a problem. So, we talked about structure. We talked about method naming, but let's just make sure this is an example of a really bad name. Register get there is no expected behavior. Just look at the assert here. Assert R equals six. result view data password length. What does that even mean? [\[53:40\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3220s) What's the assert? What are we trying to prove here? Where did six come from? Well, the name of the test doesn't really say anything. So, we have to assume that the the person who wrote this has no idea did had no idea why what to assert here. So, they just asserted something on the result. But six is also a magic number. And again, where do magic numbers come from? Well, in this case, this magic number came from here. [\[54:13\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3253s) Can you see the six? So, we have somewhere in our test, we have a mock or a fake membership provider that has a hard-coded minimum required password length of six. That's an example why our test should be setting these values in the first place so that we don't have to do this kind of stuff. Here's another example of magic values and behavior. This is an override of creating a user in the system in the fake system. [\[54:44\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3284s) Now here's the important thing. There is a a lot of logic here. So if I have a username and the username equals some user and password equals good pass and email equals an email then the status of creating a membership is success. So every user in every test to create a good user has to provide these values and somehow they magically are supposed to know that these are supposed to be the good values. [\[55:17\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3317s) What if I wanted to return a non-successful one? Whoa, that's very simple. So in the email, I would send in a string with the name, sorry, with the name of the enum for which I want the status to be. Okay. So the email instead of email should contain the name of an in value from MembershipCreateStatus. [\[55:50\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3350s) So it should be MembershipCreateStatus something as a string in the email. It's like a really powerful magical incantation that you have to really know. It's like a magic password that says sh I want you to create a nonworking status. Just look in the email. No one will find this out. Okay? There's no way for people to find this out. It's not explicit. It should be explicit. either [\[56:20\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3380s) By creating a public static property or some settings somewhere that the test would set and this would use these settings. That's how it should be. It shouldn't be hidden from the tests. It should be explicit in the test what's going to happen. which is a good idea for the interface that you are testing that it should include these types of enumerations for texts and so >> well this is not the interface >> yeah is it a good idea for the interface I'm testing to have these enumerations well this is not the interface I'm testing [\[56:59\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3419s) >> this is the stub that I'm using to test something else >> test test of this class. You have a class, you will test. So the class or in conjunction with the class, you also have these texts that you will use in the implementation of of your class or your library. And then you will use the same enumerations in the test for setup and for [\[57:33\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3453s) Checks and >> yeah so I would have some maybe shared const or enumerations that are visible in my tests through some class and then I would say that my test will create something and and use that const to create it and then here I would use the same const in this code >> and so that I would have a shared knowledge of what's supposed to happen. Yeah, >> you can have all the arrow texts [\[58:04\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3484s) Could be defined in the class or maybe if you are are checking against the error texts or contains this. If I'm looking for a specific error that's hardcoded into a stub in the system, >> then the stub would use a const and I would assert using that const as well >> so that I know where it's coming from. >> Yeah. And also maybe the class you're the you're testing if that class has defined these texts [\[58:37\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3517s) Like that you can use some post setting them >> in the I mean >> yes if the class contains the these text then I can go directly and say I'm expecting the error to be the class dot some expected error or some error default value >> because that's then that type of information is a part of the API >> that If it's a part of the API I'm testing, then I can use the con in that API to expect something. But the important thing is that even before that, I need the reader of the test to understand why should he get that error in the first place. [\[59:13\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3553s) So there should be a stop somewhere that sets a false result. I need to see the test telling that stop to return a false result. to have it both in the definition of the test and in the in the verification or >> yes I would has in your range part I would see what's going to happen and then the assert I will see what should have happened yeah here's an example of a magic number inject me and 15 not sure what 15 is could be a million different things the number of methods in somewhere [\[59:50\]](https://www.youtube.com/watch?v=Zc0eJXNKfdw&t=3590s) Number of files etc. We're talking about naming. Okay. So, what we're going to do now is, we're going to, head off to lunch and when we come back, we're going to do some, test review exercises. Okay. If you if you have this test driven, goodbye. ## Related - [Test Review Guidelines](https://www.artofunittesting.com/unit-testing-review-guidelines) · artofunittesting.com Roy's checklist for reviewing tests, grouped under readability, maintainability and trust, the pillars used in this lesson. - [Test Reviews Vs. Code Reviews - Some Helpful Tips](https://osherove.com/blog/2007/3/13/test-reviews-vs-code-reviews-some-helpful-tips.html) · osherove.com Why reviewing tests first is shorter than a plain code review, with tips, as the lesson argues. - [Logic in asserts: Creating dynamic expected values](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_142) · The Art of Unit Testing, 3rd ed., ch. 7 The 3rd edition's section on logic in asserts and dynamically built expected values, a smell flagged in the reviewed tests. - [Having more than one mock per test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5) · The Art of Unit Testing, 3rd ed., ch. 5 The 3rd edition's section on having more than one mock per test, matching the lesson's one-mock rule. - [Internal behavior overspecification with mocks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8) · The Art of Unit Testing, 3rd ed., ch. 8 The 3rd edition's section on overspecifying internal behavior with mocks, the over-specified mocks the lesson warns about. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 - [Trustworthy tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7), ch. 7 - [Magic values and naming variables](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_169), ch. 9 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [How to know you trust a test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134), ch. 7 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [How can we know we don’t have bugs in our tests?](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11), ch. 11 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Avoid setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162), ch. 8 - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19), ch. 1 - [Checking for expected thrown errors](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2), ch. 2 - [Setting up and tearing down](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_171), ch. 9 #### The Art of Unit Testing, 2nd ed. - [The pillars of good unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8), ch. 8 - [One mock per test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec5), ch. 4 - [Writing readable tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec3), ch. 8 - [Writing maintainable tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec2), ch. 8 - [Writing trustworthy tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec1), ch. 8 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Building a test API for your application](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6), ch. 7 - [First steps with NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3), ch. 2 - [Current isolation frameworks for .NET](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5), ch. 5 - [Introducing stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1), ch. 3 - [Value-based vs. state-based vs. interaction testing](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec1), ch. 4 #### osherove.com - [How to do test reviews](https://osherove.com/videos/2011/2/6/how-to-do-test-reviews.html) - [Test Review #1 - NerdDinner](https://osherove.com/blog/2009/3/20/test-review-1-nerddinner.html) - [Test Review #2 – ASP.NET MVC Unit Tests](https://osherove.com/blog/2009/3/21/test-review-2-aspnet-mvc-unit-tests.html) - [Multiple mocks, asserts, and hidden results](https://osherove.com/blog/2011/2/9/multiple-mocks-asserts-and-hidden-results.html) - [Over Specification in Tests](https://osherove.com/blog/2008/7/12/over-specification-in-tests.html) - [Readable, Maintainable, Trustworthy Unit Tests in Java](https://osherove.com/blog/2012/9/17/readable-maintainable-trustworthy-unit-tests-in-java.html) - [Test Coverage and testing angles](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html) - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) - [Try to avoid multiple asserts in a single unit test](https://osherove.com/blog/2005/4/14/try-to-avoid-multiple-asserts-in-a-single-unit-test.html) - [Naming standards for unit tests](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html) - [Isolator feature focus: Recursive Fakes](https://osherove.com/blog/2008/10/4/isolator-feature-focus-recursive-fakes.html) [Previous lesson Isolation Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/isolation-frameworks/) [Next lesson NerdDinner Test Review](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/nerddinner-test-review/) --- title: "NerdDinner Test Review" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/nerddinner-test-review.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/nerddinner-test-review/" tags: [] author: "Roy Osherove" description: "Lesson 7 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Test Review Insights), 27:17. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # NerdDinner Test Review 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 3. Test Review Insights Lesson 7 of 14 Duration: 27:17 [Watch on YouTube](https://www.youtube.com/watch?v=xjlsDaX4NEs) Roy Reviews NerdDinner project with the class ## In this lesson Roy Osherove reviews the [NerdDinner](https://osherove.com/blog/2009/3/20/test-review-1-nerddinner.html "Test Review #1 - NerdDinner (osherove.com)") tests, starting with a single test project that mixes unit and [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)"); he wants them separated into a [safe green zone](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec2 "Mapping out tests based on speed and type (The Art of Unit Testing, 2nd ed., ch. 7)") of tests that always pass. A failing HTML rendering test depends on the machine's locale, and he discusses [test names](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html "Naming standards for unit tests (osherove.com)"), var, [magic numbers](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_169 "Magic values and naming variables (The Art of Unit Testing, 3rd ed., ch. 9)") such as 999, and [mock](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") helpers that are really [stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)"). Different naming conventions show him there was no [test review](https://osherove.com/videos/2011/2/6/how-to-do-test-reviews.html "How to do test reviews (osherove.com)") process, and he objects to test dinners created in a hidden helper with a dynamic date. ## Transcript 3,554 words [\[00:25\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=25s) Let's open up the [NerdDinner](https://osherove.com/blog/2009/3/20/test-review-1-nerddinner.html "Test Review #1 - NerdDinner (osherove.com)") solution. What we're going to do is we're going to take a quick look at how to actually review other people's code and what do I think about when I look at other people's code in terms of tests. Don't ask me anytime anytime everywhere about this. Okay, so let's take a look at the solution for NerdDinner. [\[01:03\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=63s) This is a new machine. This is like a really brand new machine. Okay. So, what do we have here? Just just ignore any security dialogue that you get. It's just for the team system connection. That's why it's there. So what what am I looking for when I'm reviewing code? Well, as the first thing I look for is structure. You can see that the structure contains only two projects. [\[01:36\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=96s) There's a NerdDinner and there's a NerdDinner. That already that gives me an uneasy feeling because usually I try to have at least a couple of test projects. one will be dedicated to [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") and the other will be dedicated to [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec3 "Integration tests (The Art of Unit Testing, 2nd ed., ch. 1)") and I separate them. So first of all, does anyone remember what is the definition of a unit test versus an integration test? How how can I tell what's a unit test and what's an integration test? [\[02:08\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=128s) Any thoughts? The naming. Okay, but what if I named it incorrectly? How can I tell that someone named it incorrectly? What's the difference from a between a unit and integration test? Integration test tests all layers and might depend on the state of the system. >> Multiple layers. Yeah. Whatever. All but multiple layers. [\[02:38\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=158s) >> Okay. What else? So, here's an easy way to tell if a unit is really an integration test. If it touches the file system, if it uses the database, if it uses things that are out of our control, it's an integration test. If it's slow because it depends on something that is slow, it's an integration test. If it's not repeatable or every or it's not consistent. [\[03:10\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=190s) So every time you run the test or every se once in a while the test returns a different result. It means that there is some problem and the test is might not be a unit test. So I might actually look at the the using for the test and if it's using the file system etc. But why do I want to separate unit tests from integration tests in the first place? What's the point? [\[03:48\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=228s) Unit tests run much faster and integration test run slower. So I might not want to run my integration tests all the time. Okay, so what's preventing me from doing that? What's the I mean why would I separate so that I can right click on one project and get to run faster? So, it's good to have a separation so that I can have a series of tests that [\[04:22\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=262s) Run faster. But that does that's that's not the only reason why I would separate. Yes, I might not want to run the integration tests on the build server. Well, usually on a build server maybe at night I would want to run the integration tests. So, but the separation of units from integration is not just about selection because there are other ways to select test. For example, you can put a special attribute called category on tests and ask nunit to run all the tests with a specific category on them. [\[04:58\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=298s) The real problem that I see with mixing up unit test and integration tests is a really human problem. Imagine that you just got the latest source code from NerdDinner.Tests. You right click on this, you run all the tests. and it's compiling etc etc. We'll see what happens. But what happens if one of the test fails? [\[05:32\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=332s) Now if I'm new to the team or I don't know this test, I might ask in my team, why does this test fail? And someone might tell me, oh, don't worry about it. It uses a database, so maybe you just don't have a database. Don't worry about it. Someone might say yeah, you probably just missed a configuration somewhere, etc. So here I have 70 tests passing and one failing. Okay, that's the perfect example of such a situation. [\[06:04\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=364s) Now could it be that this is an integration test? Integration tests are more prone to failures because they need configuration. My problem is that I might think that this test is an integration test. So it's no big deal that only one test fails. But I could be wrong. I could be lying to myself. So the reason I want to separate unit test from integration test is so that if I have a project just with integration tests, they should all be passing. [\[06:36\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=396s) There should be no question whether a failing test is a problem or not. A failing test is a problem in a unit test project. So I call this the [safe green zone](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec2 "Mapping out tests based on speed and type (The Art of Unit Testing, 2nd ed., ch. 7)"). I should have at least one project in my solution. I can right click and all the tests should be passing green no matter what when I get the latest version. And that gives me some confidence in the code. If some of them fail and I then I don't and I think that they might fail for the wrong reason then I don't [trust](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134 "How to know you trust a test (The Art of Unit Testing, 3rd ed., ch. 7)") the result of the tests. [\[07:07\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=427s) So I want to be able to have at least a piece of code a a project that I know that everything there works. And by mixing them up, I'm not giving myself the chance to do that because now I have to go through and understand why is this test failing. I've never seen this test before. Let's take a look. And by the way, with test driven, you can see here whenever you have this at the output window, you can actually double click on the line because this is the line the line number and the column number. This is built into Visual Studio. [\[07:39\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=459s) And this is where it jumped us to here. So we have expected HTML and actual HTML. Interesting. Now this looks like an interesting test we can actually start with. We don't know if it's an integration test or not. Even though it looks rather interesting, we're not sure what the problem is. So this is an expected HTML and actual HTML and something was wrong there. [\[08:16\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=496s) And this is exactly my problem. I don't know if I should trust the result of this test. If this was a unit test project, then I would know absolutely for sure that there is a problem here. That's one of the reasons I want to separate. If this was an an integration test project, then the project could have its own set of instructions on how to get all the tests passing. But I would pay less attention to failures here if I just ran the test out of the box. But if this was failing in a unit test project, I would feel much more concerned. Right now, I don't know what to feel. [\[08:47\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=527s) And I want to prevent that feeling of not knowing what's supposed to happen. And even worse is I could tell myself maybe it's not that important. And it could be if we look at the output. Let's see. Blah blah blah verify rendered list of my dinners. Okay. So the name of the test is also interesting in this case. What does that mean? Verify rendered list of my dinners. Should the lists be you should know what the HTML should be? [\[09:19\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=559s) Where is the list coming from? This is the only thing. New list of RSVP. Create HTML helper. New my view class. Get my dinners to string. Interesting. So why the hell is this failing? expected blah blah blah but got something that looks different. And the problem here [\[09:49\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=589s) Is that the machine I'm running this on has a different local, a different language. That gives you an example of what happens when you're preparing strings and you assume a specific local. So it can actually fail on different machines for the wrong reasons. So this is somewhat an integration test. If we assume that all machines render text the same way and they can't. [\[10:19\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=619s) Now if we wanted to make this test compatible with all machines, we could set the local at the by default for for all the tests to always be American English if you wanted to. So we can have the amun test running specific local. But since we forgot to do this and this machine is actually running with I think Norwegian local then this is exactly why it's failing. Okay. So it feels like a unit test but the problem is that it's not really a unit test because it depends on the local of the system. [\[10:53\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=653s) And in fact a lot of our tests depend on the local of the system. We don't even think about it. But the moment you go into translation mode and various different translation languages in your own application, you realize that no no string is actually assumed to be American English. let's look at the test in particular. Do you guys have any issues with this test? Do you like it? Do you hate it? Is it amazing? [\[11:24\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=684s) Is it amazing beautiful? Is it amazingly horrible? Any thoughts? >> It's the name. >> You would change the name. >> Yeah. >> What's missing from the name? [\[11:58\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=718s) Unit that's being tested. >> What is the [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") here? To verify rendered list, we're not sure what is the thing being tested. Is this the thing being tested? Get my dinners to string or is this being tested? Is this being tested? Which one of these is it all of them together? It would be nice to know. So, the name is probably not good enough. Okay. What else other than that? Is is this test perfect? [\[12:57\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=777s) Okay. Well, revar is usually an invitation to question. Maybe you know what it means because you wrote the code, but for the reader of the test, they now have to look in two different places to understand what is the type. So, be more as more explicit as you can helps the reader. [\[13:29\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=809s) Yeah, I agree that it's it's almost like yeah, I mean I can see what the type will be here. >> I can see what the type will be here. But my problem is that when you say to people it's okay to have vars sometimes then people like to stretch the red line of when it's okay. So you give them one loophole and assume everything is a VAR. So I would just say look just just don't have VAS at all so that we don't even have to ask oursel that question. [\[14:01\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=841s) There is an interesting experiment that they did in New York a few good years ago. Many years ago I think it's called the broken window experiment. Have you heard of this? The broken window theory. It talks about the fact they had a building in New York that was run down and they it was a deserted building. They left they broke a couple of windows on the building and within a few days [\[14:32\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=872s) It was full of junkies and and you know addicts et etc and graffiti but the month before they actually kept the building clean and everything was clean although the building was fully empty for a month or a few weeks and no one touched the building. It was only until you broke a single window is that you actually gave people permission to say it's okay, you're not the first one to do something and so people took advantage of this. So it was an interesting experiment and I think it's the same a lot of times for for people [\[15:06\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=906s) Where you want to make sure that a specific standard is upheld is that you don't want to give loopholes. But it also goes to the idea of trust. Sometimes you can just trust your team to not use VAR when they shouldn't. But it's a good standard to to you can start with no red line. You just say everything and then a few weeks later to see if you can relax that a little bit if you if it's a more of a teaching tool really. Things I would change here. [\[15:36\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=936s) There are there are a few u [magic numbers](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_169 "Magic values and naming variables (The Art of Unit Testing, 3rd ed., ch. 9)") here like latitude 99 and minus 999. What does that even mean? Now the nice the nice thing that I like about this is that I used to review earlier versions of this code and it used to be much worse. So NerdDinner it appears that people are listening and the test doesn't have a lot of magic stuff here. Although this is still kind of magic. [\[16:07\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=967s) Does it have to start with 425 to be okay as an input? How long should the description be? Why are these 99? So if it doesn't exist, it could have been one and minus one. Who cares, right? So, when we have magic numbers, we'll just reduce them to the simplest [\[16:41\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1001s) Closest numbers to the beginning of the area where it's okay. So, if if it's a positive number, we'll use the first positive number. If if it's a positive number that has to be two digits long, we'll use the first one, 10. We won't use 17 because someone will ask what is 17. Or worst case scenario, we'll just extract a cons from this and say introduce a variable [\[17:15\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1035s) Some latitude. It doesn't really matter. that point is that it's some latitude and so the numbers doesn't really mean anything. Things that also I would change [mock](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4 "Interaction testing using mock objects (The Art of Unit Testing, 2nd ed., ch. 4)") helpers. Usually people call mock helpers for subh helpers. I innumerable of dinner create HTML helper. If we look at this is this helper method. [\[17:46\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1066s) Check this out. This is using [Moq](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5 "Current isolation frameworks for .NET (The Art of Unit Testing, 2nd ed., ch. 5)"). So it's creating a mock of view context to create new mock of view context. Okay. initializing it with a new controller context that has a mock context based. Now all these mocks are really [stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1 "Introducing stubs (The Art of Unit Testing, 2nd ed., ch. 3)"). They're all stubs because at the end of the test, what did we check? The assert was equals on strings. So all these mocks are actually stubs. The words are are meaningless. [\[18:18\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1098s) We have a lot of [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") things here and we're initializing. return this return HTML helper. Create fake HTML helper is probably how I would call it. I don't know if it's a real HTML helper or not. Fact that it's a mock helper may tell me this but again I would use I would call it fake helpers helper to make sure that the wording is better more complete. [\[18:50\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1130s) Now we have a different test right below this details action should return view for dinner a very different [test naming](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_168 "Naming unit tests (The Art of Unit Testing, 3rd ed., ch. 9)") convention. How would you explain that this test name and this test name are very different? How can you explain that? Any ideas why multiple people wrote this code? But just the fact that multiple people write the code doesn't mean that the test name should be so radically different. [\[19:23\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1163s) What does it mean that they're so radically different? It means that there was no [code review](https://osherove.com/blog/2007/3/13/test-reviews-vs-code-reviews-some-helpful-tips.html "Test Reviews Vs. Code Reviews - Some Helpful Tips (osherove.com)") process or [test review](https://www.artofunittesting.com/unit-testing-review-guidelines "Test Review Guidelines (artofunittesting.com)") process. There is no convention or naming convention that everyone agrees on. And people don't change existing tests that they don't like. They're they're afraid of changing them. Maybe because they don't understand. Maybe because there's a hierarchy there. Maybe there's miscommunication. And so this tells me a lot about the communication the team has between them or lack of communication. [\[19:54\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1194s) So just because different people write something doesn't mean that it shouldn't look in a coherent manner. Naming conventions are important for tests. They should be agreeable to everyone. So details action should return view for dinner. But when should it return view for dinner? every time it gets called only with when you have details for 999 whatever that means. That's an interesting magic number. By the way, what happens when you see 999 in a test? [\[20:27\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1227s) Oh, sorry. I looked at a different test. Sorry. Create control details one. So, one is much better than 999, right? Still doesn't mean anything to us. What does one mean? It still looks like a magic number to me. So what does that mean? Details one and it gets an int and it has a file not found result if it's null and then it has a repository find. [\[20:58\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1258s) So it's an ID of some of something. So where did that ID come from? So this is a magic number. We need to find out where it came from. And how do you solve this? One of the problems with this test is that the dinner with ID 1 was not created or was not set by the current test. It was set somewhere in a hidden way. It was probably created here at create dinners controller hopefully. [\[21:32\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1292s) If we look at dinners controller, we can see create test dinners right here. Okay, create test dinners. What do we have here? There's a loop and we have 100 dinners being set up. So there's a hard-coded list of dinners. They all look the same and they use the daytime now. [\[22:03\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1323s) So that means that every time our tests run, every day that our tests run, they're actually running a different test. They're not using the current date. They're they're using a a dynamic date. For this to be a real unit test, for me, it I would use a hard-coded date so we can actually have a consistency among the dinners and among the tests results. But then one day suddenly this test these tests will start failing. [\[22:35\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1355s) Now that's not a bad thing per se but I would but that means that there was that we we wouldn't be able to understand where the failure came from because these tests used to pass. We would look in many different places. >> Then you should have test for different fixed dates. I might have tests for different fixed dates or I will have integration tests for specific date ranges [\[23:06\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1386s) >> like with lists of millions of rows for like the minimum date, the maximum date, Georgian calendar, different calendars, different loces. But for a unit test, remember the point of a unit test for us is to generate some functionality in our code. not to prove that everything works all the time, but to drive new code. It's not supposed to be perfect. It's supposed to explain how things should work. Right now, it's it's also doing more things than that. [\[23:38\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1418s) Yes. The one thing I'm confusing when we check on this now was the dinners controller. the name of this [factory method](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "Trying the factory method route (The Art of Unit Testing, 3rd ed., ch. 2)") or what [setup method](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162 "Avoid setup methods (The Art of Unit Testing, 3rd ed., ch. 8)") didn't explain that they were all that dinners were already created. So I couldn't tell without stepping two steps in that be my problem. >> I fully agree you didn't know that dinners were created. That was kind of my point is that when we look at the test [\[24:19\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1459s) Create controller and let's go back here is when you create dinners you don't realize you have a bunch of dinners. you you'll realize it from now on, but there's something that's in terms of [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)") really problematic here. So I would rather say create dinners controller with 100 dinners as the name of the method so that I know where ID1 came from or I would just create a dinner controller with a single dinner which I know the ID for directly in the text in some helper method. [\[24:58\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1498s) Now I don't need the arrange act and assert here because they're already separated by lines, right? It's just an extra embellishment we don't need. Now this is interesting. Details action should return not found view for bogus dinner. Okay, that's kind of a good name. But remember that the details action that's the unit of work in this case [\[25:28\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1528s) Bogus dinner is the scenario and this is the expected behavior. So all three parts actually exist. So this test name is actually pretty good. How do we know that 999 is a bogus dinner? That's our problem. So instead of that maybe I would say fake dinner data dinners count plus one sorry like this maybe that would be better [\[26:01\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1561s) So that I know or even even better is that I would say minus one with an ID that could never exist cuz 999 could actually exist. It looks like a magic number. Or worst case scenario, [\[26:33\]](https://www.youtube.com/watch?v=xjlsDaX4NEs&t=1593s) Value that says does not exist. ID like this. But still my big problem is that I cannot I'm not creating the dinners in the same test that's using them. And so I have to guess I have to to have a mental map of how everything works in the inside. And I I'm not crazy about that. Okay. So that should get us kind of started on our way on how to look at other people's code. ## Related - [Test Review #1 - NerdDinner](https://osherove.com/blog/2009/3/20/test-review-1-nerddinner.html) · osherove.com Roy's earlier published review of the same NerdDinner tests, for comparing notes with this class session. - [Mapping out tests based on speed and type](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec2) · The Art of Unit Testing, 2nd ed., ch. 7 The 2nd edition's section on mapping tests by speed and type, the unit and integration separation Roy asks for. - [Magic values and naming variables](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_169) · The Art of Unit Testing, 3rd ed., ch. 9 The 3rd edition's section on magic values and naming variables, like the 999 and bogus values found here. - [8 techniques to find problems in your unit tests within 30 seconds](https://osherove.com/blog/2009/8/31/8-techniques-to-find-problems-in-your-unit-tests-within-30-s.html) · osherove.com Quick ways to spot trust, maintainability and readability problems when reviewing tests, as done in this review. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [How to know you trust a test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134), ch. 7 - [Naming unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_168), ch. 9 - [Trying the factory method route](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2), ch. 2 - [Avoid setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162), ch. 8 - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 #### The Art of Unit Testing, 2nd ed. - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec3), ch. 1 - [Interaction testing using mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4), ch. 4 - [Current isolation frameworks for .NET](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5), ch. 5 - [Introducing stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1), ch. 3 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 #### osherove.com - [Naming standards for unit tests](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html) - [How to do test reviews](https://osherove.com/videos/2011/2/6/how-to-do-test-reviews.html) - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) - [Test Reviews Vs. Code Reviews - Some Helpful Tips](https://osherove.com/blog/2007/3/13/test-reviews-vs-code-reviews-some-helpful-tips.html) #### artofunittesting.com - [Test Review Guidelines](https://www.artofunittesting.com/unit-testing-review-guidelines) [Previous lesson Test Review Practices](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/test-review-practices/) [Next lesson Unity Test Review](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/unity-test-review/) --- title: "Unity Test Review" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/unity-test-review.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/unity-test-review/" tags: [] author: "Roy Osherove" description: "Lesson 8 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Test Review Insights), 25:37. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Unity Test Review 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 3. Test Review Insights Lesson 8 of 14 Duration: 25:37 [Watch on YouTube](https://www.youtube.com/watch?v=2r7B5nITplA) Roy and the class Review Unity.codeplex.com tests ## In this lesson After the audience reviewed the tests of [Microsoft's Unity](https://osherove.com/blog/2009/3/23/test-review-3-unity.html "Test Review #3 – Unity (osherove.com)") project, Roy Osherove goes through their findings, including [a test with no assert](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7 "Tests that don’t assert anything (The Art of Unit Testing, 3rd ed., ch. 7)") and [setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162 "Avoid setup methods (The Art of Unit Testing, 3rd ed., ch. 8)") that hide the arrange part, which he replaces with [factory methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "Trying the factory method route (The Art of Unit Testing, 3rd ed., ch. 2)"). They discuss bug recreation tests, which belong in a clearly named class, a test that depends on release or debug build flags and is therefore an [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)"), and a structure that does not separate unit from integration tests. He ends by writing an [Assert.Throws-style](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6 "More NUnit attributes (The Art of Unit Testing, 2nd ed., ch. 2)") helper for MSTest, which lacks one. ## Transcript 3,072 words [\[00:07\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=7s) Okay. So, now that you have you've had some time to review the Microsoft [Unity](https://osherove.com/blog/2009/3/23/test-review-3-unity.html "Test Review #3 – Unity (osherove.com)") project, why don't we find out some things that have bothered you about these tests? We'll go over them together. So, who wants to go first? Yep. >> Yes. I have some some general things that repeated a lot of the the patterns repeated where the first thing is obvious and I think I didn't put it one down more than than once is the [naming convention](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html "Naming standards for unit tests (osherove.com)") is different. [\[00:44\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=44s) >> The naming convention is different doesn't necessarily mean a bad thing as long as it's consistent and it contains the three important pieces. for example, >> the thing we're testing the behavior behavior and the scenario. >> Okay. >> Okay. So, the naming convention doesn't have to be exactly like the one I'm teaching. I'm just teaching some one that would work. There are many ways to do it. >> Okay. So, so one file that I opened, I just started off the top of the Unity test project. [\[01:15\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=75s) >> what's the name? >> the Unity test the main Unity test project. >> Yeah. What's the file name that we're looking to look at? >> Build plan and child container page. >> Build plan and >> by the way this is a with your ReSharper you can just use uppercase letters for the partial words. So BPA will find this. CtrlN to find this file. Okay. Specific line number. >> So yeah in line 64 [\[01:48\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=108s) G line 64. >> Yeah. So this test there were a couple of things for this and and detect the next test below it and so we we don't have a a range and we don't have an assert the arrange is in in a setup in a test initialize on top and the assertion is implicit that nothing bad happens even says here we expect we are good I must admit that is I would say that's a bit too implicit in my opinion [\[02:20\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=140s) Okay. So, let's take a look. So, what you're saying is the test initializes gear range part. >> Yeah. >> Mhm. >> And Yeah. And there's no assertion. >> And there's no assertion here. And it even says no exception means we're good. There's no assert to anything. And you have a problem with this because >> Well, I I don't know what I'm checking here. And it's also the question. So it says we have no exception, but there's no test for the other way that we get an exception if something goes wrong. [\[02:54\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=174s) We're just having >> So he's only testing the happy cases, not the unhealthy ones. Let's take a look at the name of the test. Child containers for unconfigured types. Put constructor parameter param resolvers in parent. Okay. Parent container create child container resolve. Yes. And it doesn't throw an exception. But we're not there is no assert here to prove that something is true or false. That definitely feels like it's missing. [\[03:25\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=205s) Yes, I would agree that an assert here would make more sense than no assert. Maybe it doesn't do anything and doesn't throw an exception. That might be a case. Yeah. Okay. The fact that it could resolve it without an exception doesn't mean that it's working. >> Yeah. And Yeah. And the other issue I had with this you said that this [setup method](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_171 "Setting up and tearing down (The Art of Unit Testing, 3rd ed., ch. 9)") on the on the top >> yes >> that this would rather be nonoptimal so either using something like a [factory method](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "Trying the factory method route (The Art of Unit Testing, 3rd ed., ch. 2)") [\[04:03\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=243s) It is a bit implicit in this case the class is not so long so and but I must admit it's yeah it's it's not that I kind the test without going checking oh is there initialize if there would be a factory method or something like a setup method called I would at least know where to go here I have to check that there is something happening before >> mhm okay so yeah we could we could create factory methods of both of these like this [\[04:34\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=274s) Make parent and actually not what I meant. What I meant is that we would say like this make parent container and [\[05:14\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=314s) Make child container. And then we would just do both of these at the beginning of each test. [\[05:56\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=356s) Yeah, it definitely feel to to me I I agree that feels more readable and we still get the same [maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)") aspect. >> And the other thing is with that the next step including this is usage of fields instead of a variable sudden see the necessity to have the scope beyond that. >> You mean these fields? >> Yes, the parent no container child container. Yeah, we don't need these anymore. >> Make child. Oh, because the the parent is creating the child. [\[06:27\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=387s) Okay, that now it makes sense. >> Yeah. Well, anyway, it's a >> but we can accept this as a parameter. >> Yeah, >> this make child my parent container etc. So then we could use these factory methods by giving it the parent container here. [\[07:03\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=423s) Okay. Yeah. Now it becomes a bit of a problem if we have more tests. But I would still do that even though it became a bit more of a problem because the setup method is just that much more unreadable. Now that's assuming that all tests need a child and a parent of course that >> okay what you said especially with the mocking if you don't if you don't see the plumbing >> you mean faking >> faking whatever yeah if you don't see the plumbing between the objects it's it's all implicit you always have to go somewhere to see what's happening there >> yes >> okay good what else >> number [\[07:43\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=463s) >> where >> >> these ones >> valley injection from child and value injected from parent that's being used here. Well, they're not [magic values](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_169 "Magic values and naming variables (The Art of Unit Testing, 3rd ed., ch. 9)") because they're in cons and they're saying this is some value injected from child but it's better if it was one and two but >> yeah but should it then be it's some value be name some value? Yeah, a better name would be some value. [\[08:15\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=495s) But as long as it says value from, then if I was to assert against this in the test, I would say, oh, so I'm expecting the value injected injected from child. Then it should be no problem. In terms of [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)"), I don't think it's a problem because they're actually using it correctly. The problem is there's only one usage. So it's better to just say some value here [\[08:51\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=531s) And use some value right now because no one is using that value anyway. If they had pre-engineered this so they could use the value later but they're not. It's overeng engineering. The point of refactoring tests is that you make things as local as possible to the test and then you pull them out if you need them in multiple tests. Okay. Anything else? Yes. >> In the same file >> wasn't mine. [\[09:27\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=567s) >> I think you deleted one. >> Yeah. >> The first test is gone. >> Sure. There it is. >> Okay. This test. >> Yeah. What's the problem? >> well, I have the same things that we talk about, but we don't see. >> Okay. So, here they're actually using value injection from parent and child. So, it makes sense that it's a field though. >> Yeah. >> Okay. >> But to have two >> to have what? [\[09:57\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=597s) >> Two. >> They're testing two things. So two asserts assert are equal value injected for parent from parent and from child of value. Values injected are correct when resolving from parent first. Well here the thing is that the they're testing the ordering. [\[10:28\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=628s) >> Okay. So the [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") here spans both of these things. is that the ordering matters. So in this case, okay, >> if even one of the values is not true, then we don't even care about the second one because it's already not not correct. >> But we know which one that's >> when resolving from parent first. First means that you you're resolving more than one. So you have to have two results. So and it says values. So it means all values [\[11:00\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=660s) Injected are correct when resolving from parent first. Resolve from parent first to elicit the buggy behavior. So this is probably what happens. They found a bug and now they're reproducing it when they when using the parent first to resolve. Okay. So this would be a good place to say okay I'm putting this somewhere else. I'm putting this method or this test in a special class called [\[11:31\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=691s) Bug recreation because bugs to recreate them sometimes you you don't use a normal [unit test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)"). You would do something a bit more complicated that a user would do. It's always better to simplify and simplify and simplify. But in this case it's a bug recreation. It makes sense. It could be that this whole class was created by a bug recreation of this and then they added a couple more tests, but it would be nice to say in the class name u bug bug related tests or something like that. [\[12:04\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=724s) Okay. >> Okay. More things in not necessarily here. I mean more things that you found. >> Yeah. In the code gen bug fixture. >> Sorry. Codegen bug fixture. So control N codeg gen bug fixture. So bug fixture means they're already there they have a class especially for bug recreation. Okay. >> What's the problem? [\[12:35\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=755s) >> I didn't get very far but on the top there test for dynamic method creation in the CL this test would only fail if you run run. >> Uhhuh. Good catch. So what does that mean? >> It means that most lightweave or normal also developed on a keyboard. >> It's an [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec3 "Integration tests (The Art of Unit Testing, 2nd ed., ch. 1)"). It means that you're relying on an external system on the file system and on the build compiler flags. [\[13:05\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=785s) It's an integration test. It shouldn't be in the unit test project. Okay? because the test does not have control of whether it's being built in release or debug. So if you don't have control over everything in the test, it's not a unit test. Okay. Yeah. And this file also the [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") class that they have also have conditional. We were talking about >> can you I don't understand. [\[13:36\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=816s) >> Yeah. Sorry. The code gen class that's fake class >> or whatever it does has a conditional down there for this argument null exception and yeah so this is untested code if I if I recall correctly yeah >> this is a code that recreates the bug they're trying to throw an exception when something wasn't >> called yeah sure >> a better way to do this was to Say [\[14:07\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=847s) Assert fail static ctor was not >> old. Now it's it's easier to understand. Yeah. >> Okay. >> Mhm. Good. >> Okay. More things, more issues not necessarily in this file. [\[14:40\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=880s) What about minus 12? Here you said we should only initial once. So fix value we have that. >> Sorry. >> You said we should only report one particular problem once because the you have the the magic value thing already. I've seen this but I didn't report it because said we should report it once. >> Okay. But do you agree that Microsoft is amazingly beautiful here? >> No, but you said we should only report one thing once. >> Okay. Sorry. [\[15:11\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=911s) >> Yeah. Well, it's not difficult to see, but you said we should check for individual properties. >> Yeah, definitely. >> Yeah. >> But as I'm looking through the code, it's always nice to say, "Oh, I found another one and another one." Okay. >> okay. Anything else in another file or here? >> Okay. >> Yes. So next so next file you can open from solution explorer or directly the CodePlex issues fixure. [\[15:48\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=948s) >> CodePlex issues. CodePlex issues fixture. There are two there's one in test and one in interception extension test >> the one in unity test on top. So this is by the way the regression tests that we were talking about. So all the so all the regression tests I was wondering when you said this to the code to the other thing that we found that it was reproducing a bug. This is also reproducing bugs. >> Yeah. >> So it's really difficult to see what what's question I had. [\[16:21\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=981s) So what in terms of Unity as being a [dependency injection](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_65 "Dependencies, injections, and control (The Art of Unit Testing, 3rd ed., ch. 3)") framework that not so often relies on external factors it's this is still simulating the the whole thing we do with Unity. So the so for the nature I would rather say this was an an integration test because it's because we using >> back testing multiple things at the same time because the tests are not as simple as they could be because they're like throwing in a lot of interesting different things. [\[16:55\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1015s) I would say that there's a well these are bug recreations so they're more complicated than regular tests. If they weren't participations, they would still be unit test, but they would be like experiment tests just to play with the system and see what it feels like. I would still put them in a separate folder. If they're all in memory and they're consistent, they have full control. They're unit tests. They're automated, of course. Okay. Anything else special that you can see here? [\[17:26\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1046s) Anyone? You know again we have if it's about repetition we we have again a couple of tests that like for example in line 99 there's one without assertion and even we said this should throw here it's I think there's so it means that we're not getting an exception. [\[17:58\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1078s) Oh, it's it's [expected exception](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6 "More NUnit attributes (The Art of Unit Testing, 2nd ed., ch. 2)"). I didn't see it. >> No, you I agree. It's harder to see expected exception. >> Yeah. Okay. >> It's definitely harder when it's at the attribute level. I fully agree with that. >> Okay. >> Okay. That was a good thing. >> Okay. Any new stuff? More stuff next? What about you guys? give you some more stuff that you found. [\[18:33\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1113s) What about the basic structure that we can see here? What do you think about the structure? Let's talk about that for a second and what they chose to do. First of all, in terms of conventions, they have the source and then they have a test folder and then all the tests are the name of the same name of the project tests. Some other projects sometimes start with the word test and then the name of the project. As long as you're consistent, it should be okay. [\[19:04\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1144s) You'll notice that nothing here says integration tests, although some of them you can guess that they're integration test. For example, configuration because you're probably going to need some configuration files like here. So I can guess it's an integration test. Interception, not sure. service location not sure this might be unit test might be not test support is all the infrastructure but there's also configuration stuff here so there's still not a good separation between unit integration tests although we have a lot of different projects [\[19:42\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1182s) Test doubles and then we have test objects and utilities these. Can map generic type to new generic type create something name type build key policy generic type missing policy result. [\[20:32\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1232s) To me, it looks pretty good actually. Maybe I would separate these just to make it even clearer. But overall the test looks pretty okay. Looks simple, understandable. Expected exception. Again, we wouldn't use expected exception, but would use assert throws or something like that because with expected exception, this line could throw the exception or this line or this line. And we and only the act line is the one that's supposed to throw the exception. So, we shouldn't be using expected exception at all. >> But if you're using [\[21:05\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1265s) This is the MSTest framework that doesn't have the throws. So if I'm using MSTest, it doesn't have assert throws, but it's very easy to build my own. >> Yeah, you build catch around. >> Basically, this is how you would build your own version of assert throws in in MS or any other framework class exception [\[21:44\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1304s) Public static void exception. You can make it generic. So you can say type of t. Then you can actually take a delegate. We want a delegate that can do anything. So we can be an action or a funk. So we can have two overloads. [\[22:21\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1341s) And then basically we will do a try catch try we'll say act and catch t see am I missing something here? I'm probably missing something. We can catch any type of exception actually if you wanted to. [\[22:53\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1373s) We can say if type of I think we can even say if x is p then return. Everything's great. Otherwise throw throw X. Now if we got all the way here we can say assert fail [\[23:32\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1412s) Expected exception of type T etc blah blah blah blah. We can also do this here. Maybe we shouldn't just throw. We can say assert fail expected this but we actually got a different exception. But basically this is what we do. This is a simple way to build it. And I'm sure there's even a cleaner way to use generics to catch a specific exception where you would use type of key probably or something like that. [\[24:08\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1448s) Let's see probably means catch type should extend system exception. Yeah. So we have to say where t inherits from system exception or something to that matter. Yeah. Now it should work. [\[24:39\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1479s) Now we don't even have to do this. We can just say look we caught t so everything's great. Just return now assert fail. And probably we would have a couple of tests for this stuff. Okay, questions about this? So you see it's very simple and I guess it's too simple. That's the reason why Microsoft hasn't put this into MSTest in about four years now. Okay. Any more stuff? [\[25:16\]](https://www.youtube.com/watch?v=2r7B5nITplA&t=1516s) Okay. So, what we're going to do now is we're going to take a five minute break. We're going to prepare the next exercise and then we're going to come back. ## Related - [Test Review #3 – Unity](https://osherove.com/blog/2009/3/23/test-review-3-unity.html) · osherove.com Roy's own published review of the Unity tests, to compare with the findings the class makes here. - [Tests that don’t assert anything](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7) · The Art of Unit Testing, 3rd ed., ch. 7 The 3rd edition's section on tests that don't assert anything, one of the first findings in this review. - [Replacing beforeEach() completely with factory methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2) · The Art of Unit Testing, 3rd ed., ch. 2 The 3rd edition's section on replacing setup with factory methods, the fix Roy applies to the hidden arrange code. - [Another Entlib example: Separate integration tests from unit tests (and learn to know the difference)](https://osherove.com/blog/2005/4/11/another-entlib-example-separate-integration-tests-from-unit.html) · osherove.com Roy's critique of another Microsoft project's tests for mixing integration and unit tests, the structure problem seen here. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Avoid setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162), ch. 8 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Setting up and tearing down](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_171), ch. 9 - [Maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8), ch. 8 - [Magic values and naming variables](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_169), ch. 9 - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Dependencies, injections, and control](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_65), ch. 3 #### The Art of Unit Testing, 2nd ed. - [More NUnit attributes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6), ch. 2 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec3), ch. 1 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 #### osherove.com - [Naming standards for unit tests](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html) - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) [Previous lesson NerdDinner Test Review](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/nerddinner-test-review/) [Next lesson Using Extract & Override](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/using-extract-and-override/) --- title: "Using Extract & Override" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/using-extract-and-override.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/using-extract-and-override/" tags: [] author: "Roy Osherove" description: "Lesson 9 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Legacy Code), 21:33. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Using Extract & Override 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 3. Legacy Code Lesson 9 of 14 Duration: 21:33 [Watch on YouTube](https://www.youtube.com/watch?v=ArjAy3GvD-s) In this session Roy covers the [Extract & Override refactoring](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html "Mock Objects vs. \"Inherit & Override\" (osherove.com)") technique, and when it might be useful in [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") situations. ## In this lesson Roy Osherove introduces [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)"), from the book [Working Effectively with Legacy Code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226 "Read Michael Feathers’ book on legacy code (The Art of Unit Testing, 3rd ed., ch. 12)"), on a login manager calling a static logger: the call moves into a protected virtual method with as little logic as possible, which a [testable subclass](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95 "Partial mocks (The Art of Unit Testing, 3rd ed., ch. 4)") overrides. He extends it to simulate a logger exception, check a static web service call and control the machine name rather than [build the expected value dynamically](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_142 "Logic in asserts: Creating dynamic expected values (The Art of Unit Testing, 3rd ed., ch. 7)"). He also uses it to return [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") objects, compares it with [Moq's](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5 "Current isolation frameworks for .NET (The Art of Unit Testing, 2nd ed., ch. 5)") protected API, and discusses keeping extracted methods protected or public. ## Transcript 2,932 words [\[00:25\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=25s) Now, what we're going to do is we're going to take a look at another technique. And it's called [extract and override](https://osherove.com/blog/2012/5/16/test-driven-validation-logic-with-extract-override.html "Test Driven Validation Logic with Extract & Override (osherove.com)"). And this technique is something that I I first learned about this in the book called [Working Effectively with Legacy Code](https://osherove.com/blog/2005/4/15/book-of-the-month-working-effectively-with-legacy-code.html "[Book of the month] Working effectively with legacy code (osherove.com)"). And now we're kind of jumping into the realm of what happens when you have code that is not very testable and you don't want to use one of the profilerbased frameworks to test it. Okay, how do you refactor the code to be more testable? [\[00:57\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=57s) So here we have the example of login manager with statics. Now the problem here is that I want to test that static logger.Write gets called but I don't have a way to inject a dependency into this. So what I'm going to do is I'm going to refactor the code to make it more testable without changing the functionality. So refactoring the definition is changing code without changing functionality. So making it more testable, more readable, maintainable as long as it does exactly the same as it did before. [\[01:31\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=91s) Nothing more, nothing less. So extract and override is built on top of the idea that you can create a a function, make it virtual, then you can override it by inheriting from the class in your tests. So instead of checking that stat static logger.Write got called, I can do the next best thing. I can extract a method from this control alt m let's call it call logger [\[02:06\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=126s) In the method I'm going to make it protected and virtual it cannot be static that way I can override it in my derived classes in my tests and another another important part is that I want want the method to be to have as less logic as possible. It has to be a simple and stupid method because if it has any logic including the string here in my test, I'm going to be overwriting this method. So there is no way for me to check that the logic inside it is correct. [\[02:41\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=161s) So I'm going to get everything the method needs as a parameter. Ctrl AltP to extract the parameter. Let's call it text. And now up here we have the method. This is an earlier version of the same method. So we have this and we have call logger and they're connected to each other. So instead of checking that call logger the static logger got called I can check the next best thing that call logger got called and I assume that if this got called then static logger itself got called. [\[03:19\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=199s) That's the next best thing. So the way I [break the dependency](https://osherove.com/blog/2005/8/23/issues-in-breaking-dependencies-for-unit-testing.html "Issues in breaking dependencies for unit testing (osherove.com)") is by creating another layer of indirection in my application. Now in my code I can inherit from the class. So I can create what's called a testable login manager. [\[03:49\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=229s) I like the word testable in the beginning because it tells me that this is not a regular [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") class. This is a version of the real class that I'm testing, but it's a more testable version. And in this testable version, I've broken a dependency to make it more testable. So instead of login manager with statics, this is a testable login manager with statics. [\[04:20\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=260s) I'm just going to change all these change all testable login manager to this. So my test looks like this. In the testable login manager I override the call logger but nothing else. That means that instead of a fake class I actually have just a fake method inside the real class. Everything else around this method behaves just the way it did. But this method itself isn't really calling the static logger. It's just saving the value [\[04:52\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=292s) Just like we do with every other just like we do with the every other fake class. In this case, it's just a fake method. We save the last log message as a public field. Testable login man me manager with statics. I then create it in my test. Instead of the real class, I create the testable class. I call as login. Okay. And then I use StringAssert to prove that the lm.last message [\[05:25\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=325s) Contains what I'm expecting. And this is the basic idea of extracting override. I can take this a bit further. And you'll see just how powerful this idea really is. First of all, it doesn't force me to introduce a new interface into the system. So it has very little impact and also I can I can break with it almost anything. Let's say that I wanted to prove that not only logger gets called but in a separate requirement I would have if call if the logger throws an exception I wanted to catch it and call the static web service. [\[06:08\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=368s) Okay. So I can take the static web service and I can prove this was called just like I did before. extract call web service but this time instead of getting the logger exception I don't I don't want to have this logic inside so let me just make this protected virtual [\[06:39\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=399s) And instead what I'm going to do is I'm going to extract this whole thing as a parameter because if I extract fact this is a separate parameter and this is a se separate parameter the plus here is actually a piece of logic I won't have any test that proves that I'm connecting these two things so instead I'll extract both of these as the expected message and I don't need the logger exception anymore like this so now this method is again pretty stupid [\[07:12\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=432s) And all the logic of connecting the message in the current environment machining is in the call to the web service. So now if I wanted to I could have a test that uses testable login manager but this time if I wanted to simulate an exception I could put another field public exception to throw equals null. [\[07:43\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=463s) And now I could say something as simple as if to throw is not null then throw whatever it is you need. And now I need to also override the other method call web service and not call the base because then I wouldn't have done anything. I didn't break anything. But here I can just save to let's say last web service [\[08:18\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=498s) Message equals text. Let's make this field. Make it public. That's all I'm doing. And I'm going to assert that the text here is going to be saved to to be saved. So if I write this as a new test, I can say is login. Okay. But the logger throws an exception. [\[08:48\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=528s) Then it calls the calls the web service with message and machine name. Okay. So now again I will use the testable login manager with statics and I will say lm to throw equals new [\[09:19\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=559s) Exception or whatever I want to simulate. Dude, this is totally a fake exception. Then I would still do the same thing is login okay with something and pass [\[10:00\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=600s) Dude, this is totally a fake exception. We can also just contain the current machine name. This is where things begin to get interesting. I can use the current machine name, but I don't want to do this. Plus environment machine name. Why is this not a great idea? H >> yeah well u [\[10:32\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=632s) The machine name will be different you may want it somewhere else and and yeah >> exactly the machine name is going to be different on every different machine now that's not a bad idea per se but the problem is that that means that this test is going to be a different test every time it runs on a different machine and what we want from a [Unit test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") is consistency. So we want to control the machine name so that it always is the same. If you wanted to prove that we can that the machine name local is working etc. [\[11:05\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=665s) We would use an [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)"). But for now this is this is the beginning of our solution. We can choose that it contains but if we knew the machine name in the first place we wouldn't need to do this because this is logic inside my test and most likely I'm also repeating production code from here. So this is really important. This could be a big problem. If there is a bug here for example a missing space and it's also missing in my production code I'll never find out because my test is also expecting no space. [\[11:39\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=699s) So, I'd rather have fake exception on machine name. This is much better for me, more readable and expectable. How do I control the machine name? Well, I go back to the blogging manager with statics and I I'll use extract and override again because environment domachine name machine name is just a static property. [\[12:12\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=732s) A property is just a static method. So I can go ahead and extract that again. Extract to a method get machining. I like methods better than properties. I don't know why. It just feels righter, more more more correct. And again, make it protected virtual. And now I can have full control of the machine name here in the testable version. I can override [\[12:44\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=764s) Get machine name. Now I could say machine name, but that would be a problem. It would be a problem because the reader of my test is going to look and say blah blah blah blah on machine name. Where the hell did machine name come from? So in terms of [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)"), it's going to look like a magic string. And I want my test to be fully readable. So I don't want my testable and fake classes to have this kind of logic inside them because it hurts readability and I don't want the reader of my test to look in two places to understand what's going on. [\[13:23\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=803s) So instead I will tell it to return machine name. So my test is going to say this lm dot machine name equals machine name. Let's make it into a field. That's it. I'm not even going to use a property again because a field is simpler than a property in my tests. [\[13:56\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=836s) So now I can read the test. I can see machine name here and I can see it here. I can see this here and I can see this here and I can fully understand this and I don't have a problem with the the fact that I'm repeating myself in this test because I'd rather repeat myself than hurt the [trust](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134 "How to know you trust a test (The Art of Unit Testing, 3rd ed., ch. 7)") of creating something dynamically that I assert against. I don't want I'd rather not have bugs and this is not a big maintainability issue and it definitely helps the readability. So, as we've seen, extract and override is really powerful and it's actually very simple to do. [\[14:31\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=871s) You just have to get used to doing this. Now, most of the frameworks out there support extract and override. As we've seen, I have an example here with [Moq](https://osherove.com/blog/2012/6/27/the-future-of-isolation-frameworks-and-how-moq-isnt-it-for-n.html "The future of Isolation frameworks, and how Moq isn't it (for now) (osherove.com)"). If you had such a thing with Moq, you could do [mock](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") of let's say login manager with virtual method and lm.protected because it method is not public. setup write to log to to accept this and then it gets called but we can also say dot [\[15:04\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=904s) What was it we can also tell it to return various things sorry doesn't really matter how to do it right now the the the the the important thing is that this API exists in all of the frameworks so if you wanted to you can use the framework to do it if the method that you we extracted we would make it public then it would work just the same as any other method that we can override. Okay. Personally I hate this API inside inside the Moq because [\[15:41\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=941s) If I wanted to verify it I have to say verifiable here and then I have to verify here. It's kind of a problem. So most of the time I actually use the testable version of something and if there are a lot of methods to override in a testable version then I would use one of the frameworks. Are there any questions about this before we continue? I'll show you another case where this is really helpful. Let's say that we don't have just a static method that let's say that we have a future object. [\[16:16\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=976s) We can use extract and override not just to fake a value but we can actually use it to return a fake object. Let's say that we could if we wanted to inherit from real logger if we could do that we could extract this thing into a virtual method that returns anything that inherits from real logger or ILogger in this case. So we can say extract method like a get logger and this method [\[16:46\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=1006s) Public public static would make it to protected virtual ILogger get logger. By default it returns the real logger but then in our testable version we could return a fake logger. So then anyone who wants to get an instance of a logger actually gets an instance of a fake logger. So extract an override can be used not just to check that the method got called. It can also be used to return fake objects and fake values. Another example [\[17:17\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=1037s) We can use it just like we use it for environment name we could have used it for configuration settings or for or here we can actually give ourselves two options the same as here. We could either get return here a fake web service or we could fake the whole thing here into a virtual method. So we have two choices of which scope we want to fake the do we want to return a fake object with an interface or do we just want to prove that some virtual method got called? [\[17:50\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=1070s) The choice is up to us but both of these will be really easy to do. Okay. Now, most of the time I will check that the method got called because it's easier than returning a fake object, etc. It makes test more readable. But I still don't have really great ideas on when to use which. Sometimes something feels a bit wrong with just overriding the whole thing, but at the end of the day, it's almost the same. [\[18:20\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=1100s) It should making sure that everything gets sent in with the correct string, etc. Both of these will work just the same. So you can use this as really really powerful technique to to work on with a lot of [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10 "Working with legacy code (The Art of Unit Testing, 2nd ed., ch. 10)") bases. Another option where I've seen this really helpful is if you have a method with a lot of logic inside it that gets that depends on a lot of decision- making like if this is true then do this, if this is true then do this or a method that does a lot of verifications like validations on an email or details and so then you can just extract and override each one of the validations. [\[18:56\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=1136s) So that you can set set a lot of flags very easily from the test. You can say in the test this validation will return true, this validation will return false, this will return false. Now let's see what happens. So extracting override is really powerful for that kind of stuff as well. Yes, >> one question. If we have the way in extracting to a protected method, we have to we either get the ugly API in case of Moq or it's it's not an issue if you have our own test version of that class. [\[19:28\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=1168s) But if we if we say it's it's not an issue for us and we make it a public method, we can just use it and it's virtual. We can we can just use it with a normal way of of using the marketing classes. Yeah. >> Yes. >> So the it really I I see see a big point with a special test version. So that sort of thing. But you would say just yeah. Yeah. I still not decided what I would prefer more just because otherwise we get a lot of classes just for these test versions. [\[20:05\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=1205s) And other hand we just have it potentially repeated in the in a test. So and >> so you're you're still undecided whether you like keeping things protected or keeping things public. >> Well personally I I I like keeping them protected because I don't want to make too many methods public >> because it kind of spoils the API. On the other hand yeah because the point is that this method signifies to me that an external resource got called. [\[20:36\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=1236s) >> Mhm. >> and if it's public it's like calling the external resource directly. >> So you would have in that public API one method that eventually calls another public method. >> Yeah. And so it it kind of feels weird in terms of design, but so if if it wasn't meant to be public in the first place and is just to satisfy a compiler, I'm not sure it's a good idea. >> Yeah. Yeah. >> But I could be wrong. [\[21:06\]](https://www.youtube.com/watch?v=ArjAy3GvD-s&t=1266s) I still I'm still in dilemas about this myself. >> Other questions? Okay. So continue the exercises from login manager with statics. Okay. Don't use any of the frameworks for now. Just use extract and override. ## Related - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5) · The Art of Unit Testing, 2nd ed., ch. 3 The 2nd edition's section on variations of refactoring techniques, where it covers extract and override for fake results. - [Mock Objects vs. "Inherit & Override"](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html) · osherove.com Roy compares mock objects with subclassing and overriding a virtual method, the extract and override approach shown here. - [An object-oriented partial mock example](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4) · The Art of Unit Testing, 3rd ed., ch. 4 The 3rd edition's object-oriented partial mock example, its name for overriding a method in a testable subclass. - [Achieving And Recognizing Testable Software Designs – Part I](https://osherove.com/blog/2006/3/19/achieving-and-recognizing-testable-software-designs-part-i.html) · osherove.com Roy's article on achieving testable designs, which touches on extract and override among other refactorings. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Read Michael Feathers’ book on legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226), ch. 12 - [Partial mocks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95), ch. 4 - [Logic in asserts: Creating dynamic expected values](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_142), ch. 7 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 - [How to know you trust a test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134), ch. 7 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 #### The Art of Unit Testing, 2nd ed. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Current isolation frameworks for .NET](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5), ch. 5 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10), ch. 10 #### osherove.com - [Test Driven Validation Logic with Extract & Override](https://osherove.com/blog/2012/5/16/test-driven-validation-logic-with-extract-override.html) - [\[Book of the month\] Working effectively with legacy code](https://osherove.com/blog/2005/4/15/book-of-the-month-working-effectively-with-legacy-code.html) - [Issues in breaking dependencies for unit testing](https://osherove.com/blog/2005/8/23/issues-in-breaking-dependencies-for-unit-testing.html) - [The future of Isolation frameworks, and how Moq isn't it (for now)](https://osherove.com/blog/2012/6/27/the-future-of-isolation-frameworks-and-how-moq-isnt-it-for-n.html) [Previous lesson Unity Test Review](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/unity-test-review/) [Next lesson Static Forwarding on a real legacy app](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/static-forwarding-on-a-real-legacy-app/) --- title: "Static Forwarding on a real legacy app" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/static-forwarding-on-a-real-legacy-app.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/static-forwarding-on-a-real-legacy-app/" tags: [] author: "Roy Osherove" description: "Lesson 10 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Legacy Code), 13:44. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Static Forwarding on a real legacy app 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 3. Legacy Code Lesson 10 of 14 Duration: 13:44 [Watch on YouTube](https://www.youtube.com/watch?v=z_e7igVhAeU) another refactoring technique ## In this lesson In BlogEngine.NET, downloaded from CodePlex, Roy Osherove looks at the static Send method of a ping manager class, which finds links to other blogs in a new post and sends trackbacks or pingbacks. Since the class is static, [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") cannot be used, so he creates a static forwarder: the static method calls a non-static copy on a new instance, whose dependencies become virtual methods. He advises having [integration tests before such a risky refactoring](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_225 "Writing integration tests before refactoring (The Art of Unit Testing, 3rd ed., ch. 12)") and sets an exercise: test when trackbacks and pingbacks get sent. ## Transcript 1,834 words [\[00:25\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=25s) So what we have here is the blog engine which we just downloaded from CodePlex. Our exercise for the for the rest of the day will be to write some tests for it. But first I'm going to show some another technique for working with [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") that will help us get some this this thing under test. So be because our first exercise will be about writing tests for this without anything like [Typemock Isolator](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html "Minimizing unit Test Fragility – 8 features in Typemock Isolator to help (osherove.com)") etc. then we're going to have to learn how to do some extra refactoring stuff. [\[00:59\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=59s) Now, this project surprisingly actually does have some tests, but if we look at them, the tests are unusually simple or even simplistic. A lot of them are [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)") actually. There's some tests for loading files and making directories. [\[01:31\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=91s) There's some tests for creating posts and some tests actually use IE which means that these tests are integration tests that are using selenium if I'm not mistaken to run an instance of the browser and actually click buttons and links and then check various HTML on the page. So these are not [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)"), but they are very helpful when you're working with legacy code. [\[02:03\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=123s) For now, we're not going to try to make these tests fast because we're missing all the libraries for running these integration tests. But you can take it as an exercise to try to get these tests to run. But later, not today. What we're going to do is we're going to write some tests for a blog engine manager. Nothing like a core manager class. [\[02:34\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=154s) So this is actually a ping manager class our main interest in this class is the send method. So manager send is going to be our main interest here. So first of all let's talk about what the purpose of this is. Blog engine is a blog engine. You can install it and you can create your own blog. blogs. [\[03:04\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=184s) At the at the bottom of each post of a blog, there is a thing there are a couple of sometimes we get automatic links that get posted into there. These are called pings or trackbacks. Pings and trackbacks allow us to create instant conversations when someone else talks about us. And we can create instant conversation in someone else's blog by having a link to their blog in our blog. The the purpose of the send method here is to basically go through the HTML of a new post we just created and search for links to external blogs. [\[03:42\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=222s) And then for each one of them to try to send a ping to a special server out there which collects this information and then that server saves the information and and when that when other blogs ask the server did someone talk about me it will say yes here's the link to whoever talked about you. So it's a way to connect blogs without talking to each other directly. pings and trackbacks only differ by the amount of information they collect if I if I'm not mistaken. [\[04:12\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=252s) But the basic idea is that we have blog settings whether trackback is enabled. We try to send the track back and if we can't send the track back or there's there was a problem where it's not enabled, we send a ping back. So there are two possible [end results](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)") from this [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)"). Okay, one end result is this. Another is this. So our main our main problem is going to be how to test that this was called when it was supposed to with the correct message or that this was called when it was supposed to with the correct message. [\[04:48\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=288s) And there are several things that are going to get in our way when we go through this because these methods are actually static. We cannot replace the instance of trackback to make sure it was called because send is a static method. Luckily, we can maybe use [extract and override](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html "Mock Objects vs. \"Inherit & Override\" (osherove.com)") to check that something got called. The same here. We also have track back sorry blog settings instance which is a singleton [\[05:23\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=323s) Which we will probably need to break as a dependency as well because we don't want to use the real file system. So, we could use extract and override here as well or create an interface with I settings. But there's another problem. We can't extract and override these things because the class that we're in is a static class. It cannot have non-static methods. So, send is a static method. All the methods here are actually static methods like get track back URL from page, [\[05:58\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=358s) Get URL from content. Okay, so if we just try to write a simple test for this, what's going to happen is that we're just going to get through all these dependencies and nothing's going to work. So how do we make this class more testable? Well, to get rid of the whole idea of the static so we can extract an override, we can do what's called a a static forwarder. [\[06:30\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=390s) We can keep this static method here, but just a signature. So, what I'm going to do is I'm going to actually create a copy of this cl this method, duplicate it, and have the static removed. and call it send non-static for example. But the problem is that the compiler will say but you're in a static class. [\[07:03\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=423s) So I'm actually going to remove the word static here to make things more testable. The only difference between when I have the word static or not is that the compiler will shout at me if I have non-static methods. So it's kind of useless for us. Now that I can have a non-static method, I'm going to go to the original static method and say just create an instance of new manager and call send non-static with the exact items. [\[07:38\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=458s) So it's a static method that all all that it does is just forwarding the information. And the reason I need the static method is because I don't want to break all the existing callers to the method. Okay, this way the refactoring doesn't break the whole system, but it does allow me to now actually have a manager class that has instance methods. And now I can go to all the private static methods here. What's a private static method? [\[08:09\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=489s) It means it's only going to get used by this class. So it doesn't really matter if it's static or not. And I can make them even protected and virtual. And I can then go and say, okay, I want to break something. Let's go to blog settings, enable trackback send. And instead of actually using a file, I can just extract a method from it and says [\[08:44\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=524s) Enable trackback send and don't make it static. Please make it virtual. And that's it. Now in my test I can actually create a testable manager class that overrides this method and returns whatever we want without using a blog settings configuration file. And the same I can do from anything here. For example, get URLs from content. [\[09:15\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=555s) What does that even mean? It means it goes and it downloads the actual URLs from links inside my content. If I did that, then I'm relying on the web to be present in my tests. It will become an integration test. So I can override this and return whatever I want. The same here like this whole thing remote file. I don't want to have a remote file whatever that means like read from web. [\[09:46\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=586s) Get track back URL from page parses using regular expressions. If a regular expression is too complicated to generate inside a test so I will easily find something then maybe it's a dependency as well and finally I can just extract and override these things to extract this into a virtual method etc. So again what I did to make this testable is I removed the static [\[10:16\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=616s) And I made I took the existing static method created a copy of it which is non-static gave it a different name and made the static method just forward to a new instance of my class and called the non-static method. Yes. But in a reality or in a real life case we would we if we don't have any tests in a legacy code we would rather sub integration test first before we do this. Yes. In the real world what you would do before you would do this because this is really risky is that you would have at least one or two integration tests that really use the web page and everything to make sure that the existing flow doesn't break and then you can refactor. [\[10:59\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=659s) I wouldn't recommend this kind of refactoring without any integration test but it's worth it. An example is that one time I was sitting with a person I was consulting for them. They had a big legacy system written in C++ and they wanted to add a new attribute to the configuration file. Okay. But they we wanted to do it in a [test-driven](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") way. So what we did is first we wrote an integration test that actually loads the entire system in memory and with the old configuration file and we checked that the settings were loaded. [\[11:33\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=693s) And then we wrote another test that loads them and then checks for the miss the new setting that was not there yet. And then we made it pass with the attribute. So we actually did a test-driven integration test. It was still worth it. >> >> other questions? Okay. So what I want you to do is I is as an exercise I want you to write a couple of tests or more that prove that trackback send gets sent [\[12:10\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=730s) When you have at least one URL that in the content of a post it get you want to prove also that it gets sent that it gets called twice if you have two right because basically let's see. There's a loop here. So, you want to make sure this loop actually works. So, you want to prove that if you have just one, it gets called once. If you have two, it gets called twice. [\[12:40\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=760s) And you also want to prove that if the configuration says that you should not enable trackback, then you should send a ping back. Okay. You can also prove that if the trackback URL is null because there is no trackback URL then it should send a ping back. All these things have a reason. So we should test them. Okay. So the refactoring we saw was create a static forwarder [\[13:12\]](https://www.youtube.com/watch?v=z_e7igVhAeU&t=792s) And then you can use extract and override. Okay. Good luck. If there are any questions, just let me know. >> No, you don't have to write the integration test for now. Just write the unit test as if you have integration. ## Related - [Writing integration tests before refactoring](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10#ch10lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 10 The 2nd edition's section on writing integration tests before refactoring, the safety net Roy advises before static forwarding. - [Issues in breaking dependencies for unit testing](https://osherove.com/blog/2005/8/23/issues-in-breaking-dependencies-for-unit-testing.html) · osherove.com Roy on ways to break multiple dependencies in an existing class or method, the problem the ping manager poses. - [Read Michael Feathers’ book on legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226) · The Art of Unit Testing, 3rd ed., ch. 12 The 3rd edition's pointer to Michael Feathers' legacy code book, the source of the static forwarding technique. - [Tips for Testable code and for testing legacy code](https://osherove.com/blog/2007/6/10/tips-for-testable-code-and-for-testing-legacy-code.html) · osherove.com Roy's consulting notes on getting a hard-to-test business method under test in legacy code. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Writing integration tests before refactoring](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_225), ch. 12 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19), ch. 1 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 #### The Art of Unit Testing, 2nd ed. - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 #### osherove.com - [Minimizing unit Test Fragility – 8 features in Typemock Isolator to help](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html) - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) - [Mock Objects vs. "Inherit & Override"](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html) [Previous lesson Using Extract & Override](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/using-extract-and-override/) [Next lesson Testing Legacy Code with Typemock Isolator Deep Dive](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/testing-legacy-code-with-typemock-isolator-deep-dive/) --- title: "Testing Legacy Code with Typemock Isolator Deep Dive" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/testing-legacy-code-with-typemock-isolator-deep-dive.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/testing-legacy-code-with-typemock-isolator-deep-dive/" tags: [] author: "Roy Osherove" description: "Lesson 11 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Legacy Code), 20:08. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Testing Legacy Code with Typemock Isolator Deep Dive 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 3. Legacy Code Lesson 11 of 14 Duration: 20:08 [Watch on YouTube](https://www.youtube.com/watch?v=vst-gq7-iqs) Roy Tests BlogEngine.NET with Isolator ## In this lesson Roy Osherove tests the same blog engine code with [Typemock Isolator](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html "Minimizing unit Test Fragility – 8 features in Typemock Isolator to help (osherove.com)"), explaining why Visual Studio must be restarted for a [profiler-based framework](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") and what the Isolated attribute does. He fakes the static methods of the trackback class to verify that Send was called, then follows each failure, which he calls [wishful invocation](https://osherove.com/blog/2010/3/19/code-excavations-wishful-invocations-perimeters-and-domain-s.html "Code excavations, wishful invocations, perimeters and domain specific unit test frameworks (osherove.com)"), faking a non-public static method, the blog settings singleton and all instances of a remote file class. The test passes without any debugging, and he asks the audience to get to the same point. ## Transcript 2,283 words [\[00:26\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=26s) So now let's look at the blog engine, but this time we're going to try to do it with [Typemock Isolator](https://osherove.com/blog/2006/9/27/using-typemock-vs-design-for-testability.html "Using TypeMock vs. Design for testability (osherove.com)"). So I'm going to show some of the APIs we can use and some of the thought process. We're not going to solve it fully. We're just going to start working with it. So our problem is first of all to to start using Typemock Isolator, I installed it and restarted Visual Studio. It's important to restart Visual Studio because because it's a profilerbased framework. The only way a profiler works is if you have an environment variable in the process where the tests run. [\[01:03\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=63s) And what isolator and [Moles](https://osherove.com/blog/2010/5/25/justmock-and-moles-a-short-overview-for-tdd-alpha-geeks.html "JustMock and Moles – A short overview for TDD alpha geeks (osherove.com)") and JustMock do they install a plugin into Visual Studio when loaded simply loads an environment variable. And so all the tests in Visual Studio run with that with the Visual Studio environment variables. And so they run with profiler enabled. If I didn't do this then my test will just fail because the profiler doesn't work. And then I added two references. Basically I went and said right click add reference. [\[01:36\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=96s) I looked for T for Typemock and I need the C# APIs and the core DL. So just this these two. If you're looking for them, they're in the Typemock Isolator 62 range act and assert and Typemock dl. Next thing I do is I created a in the [unit test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") project I added the class called manager tests [\[02:06\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=126s) And I added the isolated attribute. The isolate attribute makes sure that if that if I set static behavior in different locations in different tests then they get cleaned up between each test run. If we forget to do this our test can start behaving in a weird way. I could have instead do done just isolated at the test level and then I would have to remember to do it for each test. If I do it at the class level, it works for all the tests in the class. [\[02:43\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=163s) So this is the beginning of the test that I that I that I wrote. If I just want to call manager send I'm I'm still still going to call send. So we'll have this dependency and everything. [\[03:15\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=195s) If I was to call manager.send, I need to create a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") publishable bull item. So I can just call fake item here and also send in a URI. So we're just going to send in some URI here. [\[03:47\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=227s) Equals. And now I'm going to use isolator to fake it. Isolate fake an instance of I publishable. That's it. Now, if I just do this, what is my end? What should be my [end result](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)") here? What I'd like to do is I'd like to be able to ch make sure that trackback.sam got called because that's one end result. Another end result would be to track that pingback. [\[04:19\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=259s) So let's start with this. I want to track that trackback. So I should start tracking it by saying isolate fake static methods of type trackback. And the reason I'm not saying just a specific method I could have done this isolate fake or sorry isolate when called trackback send [\[04:52\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=292s) With anything ignore since it has to return something we can just say return [recursive fake](https://osherove.com/blog/2008/10/4/isolator-feature-focus-recursive-fakes.html "Isolator feature focus: Recursive Fakes (osherove.com)"). It's the same as saying ignore call. Just return whatever it needs to return. The reason I'm not doing this and remember I'm sending in here null because by default isolator doesn't care about parameters. If I wanted it to care about the parameter I would have to say with exact arguments [\[05:24\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=324s) And then it would care. Right now it doesn't care about the parameters. So it always returns a recursive fake. In this case it returns always a default value. I could have done this, but I might as well fake all the static methods of trackback if I don't care about it really because it's a different class and it's a different location. I might as well fake all of them because I don't care about any of these static. So, I'm just going to do that. [\[05:57\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=357s) Now, if I wanted to verify it got called, I can say isolate.verify And then I can choose for example I can verify that something non-public got called or if it's public I can say it was called for now we can say with any arguments trackback. And if it didn't get called my test will fail. So if I just run this, [\[06:46\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=406s) Okay. Now just to prove that we can get this to to be called. Even if I in my test I call it directly just to prove a point can say trackback. send with anything or just a fake item. Who cares? So, trackback message, sorry. New track back message with the fake item and the new URI [\[07:17\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=437s) With something. Did I miss anything? Too many braces. H >> the constructor has three parameters. >> Oh yeah, it has two URIs, right? Yeah. And again a new URI. So I'm just going to do this for now. [\[07:50\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=470s) Ctrl + D to duplicate. And hopefully now we will end up with something. Or you know what? just say this. Well, that's it because it doesn't matter for our demo purposes. I'm going to repeat the test. I pressed alt R and you can see here one passed. So, it actually got called. I remove this. [\[08:23\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=503s) I alt R again and the test fails. Okay. So now that we can track it, we can start doing interesting things. If we actually run this, our test fails because it didn't get called. But now we can go deep and find out why it's not called. What should happen? If you go into manager send, [\[08:54\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=534s) We'll see that somewhere we have a get URLs from content. Okay. Now, right now it's protected virtual because I I I I refactored it. What if I turn it back into static? Private static. Get yours from content. And just repeat the test for now. Build succeeded. Still failed. Okay, if I wanted to control get URLs from content so that I get back some URL because it's non-public, [\[09:31\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=571s) I can either turn it into public or I can use one of the these APIs. Isolate when non-public dot when called. Now the target object is there is no instance because it's a static method. So it's a type you can just say type of manager [\[10:03\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=603s) With the method name of get get urls from content and I can also tell it what to return when called will return. And now I can return a new list of URI URIs. So if it's expecting get URLs from content which is an innumerable URI [\[10:34\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=634s) We can say list and create a variable of list of URI equals new list of URI and initialize it with a couple of them or maybe just I http [\[11:11\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=671s) So we have this new list. We don't even need this for now. This list is going to be returned. I just make it even more readable. I think right now get else from content will return list. Now let's see what happens. So now I get a a weird stuff. System null reference exception object reference not sent to an instance on of an object. If I look at the stack trace I can see blog engine core get current instance. [\[11:41\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=701s) If I go back double click here blog settings.get instance and then somewhere here I have if blog settings instance enable trackback send. So I've come across another dependency and this is a very common pattern of work in [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") that we've talked about which I call the [wishful invocation](https://osherove.com/blog/2010/3/19/code-excavations-wishful-invocations-perimeters-and-domain-s.html "Code excavations, wishful invocations, perimeters and domain specific unit test frameworks (osherove.com)"). So again basically what I'm doing is I'm trying to write my test here [\[12:13\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=733s) And then I invoke something and I wish that it works. If it does it's great. If it doesn't, then I look up at the track race trace. I see what I missed and I continue faking away until I can actually get through the path that I'm working on. So if I've realized that this is a dependency, if I didn't have isolator, I would have to [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") this or something. But here now what I can do, I have several choices. I can just say [\[12:46\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=766s) Isolate when called blah blah blah ignore call or return recursive fake or I can just say will return true because I wanted to enable trackback send and this will take care of everything. If I didn't care about the result, I could have just faked all the static methods on the type of blog settings. [\[13:18\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=798s) That would make things even better for me because then I wouldn't care about each specific method. But right now, what you can see is that I can fake a chain of things. Blog settings has an instance and that will be fake by default. So if I run this again, no debugging yet. I look at the output and now I have another exception. The remote name could not be resolved. [\[13:49\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=829s) Something.com get response. So it's actually going out to the web and trying to download something because it's going through a remote file. So if I go here, it's saying remote file get file as string and then get trackback URL from page. So these two lines are actually a dependency as well. These are actually downloading the the content of the file. So how do I take over instances of things that are mued up? [\[14:22\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=862s) One way to do it would be to just use the isolator future syntax. So we can say we could create a fake instance of remote file. Or so the first way would be to say isolate fake instance of remote file file. Now remote file currently is internal. [\[14:54\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=894s) I'm going to make it public for demo purposes. But in real life, what you would probably do is you would use the [InternalsVisibleTo attribute](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6 "Overcoming the encapsulation problem (The Art of Unit Testing, 2nd ed., ch. 3)") in the in the production code so that your test will see it as if it was public. So isolate fake instance of remote file. Let's get back the instance fake remote file. And now I can say isolate fake swap [\[15:26\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=926s) All instances of remote file with the fake file. I could have done instead isolate swap all instances on remote file with a recursive fake and then I wouldn't need the file at all. So this is like a shortcut. If I don't care about the specific behavior of the fake object, [\[15:58\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=958s) Then I can just say, "Look, fake an object for me and replace all the future objects with a fake one that just does all the defaults. If I care about how that fake would behave, then I would fake it on my own and I would tell it to replace it with my own." Okay, so what happens if I just fake it with with a recursive fake? I run the test again, go through the output, I get a verify exception was expected but was not called. Now I'm not getting an exception. [\[16:30\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=990s) So I'm not I don't know what the dependency is or not, but I might be just not going through the path as as as well as I thought. So now might be at the time to either debug or if I look at this get trackback URL from page it might be that it's getting a page content which is empty from that fake file. So what I would want to do maybe is to say get track URL from page. I can either go there and [\[17:04\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=1024s) Make it match a specific regular expression as the fake content. And let's see what the regular expression is. It looks for trackback.ping blah blah blah blah blah blah blah. And what if it's too complicated? What if creating the content that is so complicated for this is actually has become so complicated it's a dependency. Well, in that case I can just fake the validation of the regular expression. [\[17:38\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=1058s) So instead I'm just going to fake this get track URL from page is going to return some kind of non-null trackback URL. Okay. So this is going to I'm going to make this return non trackback URL. And this was initially static as well. So I'm going to make it static back again. Private static. So again I'm going to go here and say let's duplicate this and say when called on manager [\[18:09\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=1089s) What was the name of it? Get track your from page. We'll return new what was it? What's supposed to happen? Supposed to get a track URL. What's the type URI? Okay, it's going to use that URI. So, I'm just going to send in a new URI [\[18:44\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=1124s) URI that is keep forgetting the HTTP I don't know why must be a psychological thing. something.com. So now get track URL from page is going to return something that's not null. Repeat the test. Alt R. Let's see the output. And now it actually succeeded. And I didn't do even a single bit of debugging yet. [\[19:14\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=1154s) Okay. But at some point in legacy code, I would get into the idea of debugging. Sometimes you do have to debug. Are there any questions so far? So I didn't touch the code except actually make it harder to test so that it would feel a bit more like legacy. Are there any questions so far? Okay. So, what I want you to do, I want you to install Typemock Isolator. And I want you to get to this stage [\[19:45\]](https://www.youtube.com/watch?v=vst-gq7-iqs&t=1185s) Where you can actually prove that trackback.send got called. Okay, ## Related - [Important tools for legacy code unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10#ch10lev1sec4) · The Art of Unit Testing, 2nd ed., ch. 10 The 2nd edition's section on important tools for legacy code unit testing, including profiler-based isolation tools like Isolator. - [Video: Typemock Basics - Lesson 1 (Dependency breaking 101)](https://osherove.com/blog/2008/1/21/video-typemock-basics-lesson-1-dependency-breaking-101.html) · osherove.com Roy's short screencast on breaking dependencies in legacy code with Typemock, the same tool used in this deep dive. - [Easier legacy unit testing with TypeMock.NET](https://osherove.com/blog/2005/3/20/easier-legacy-unit-testing-with-typemocknet.html) · osherove.com Roy's early post on using TypeMock to test legacy code that can't easily be refactored. - [Isolator feature focus: Recursive Fakes](https://osherove.com/blog/2008/10/4/isolator-feature-focus-recursive-fakes.html) · osherove.com Explains Isolator's recursive fakes, which return fake objects from properties as the lesson's fakes do. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19), ch. 1 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 #### The Art of Unit Testing, 2nd ed. - [Constrained and unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1), ch. 6 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 - [Overcoming the encapsulation problem](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6), ch. 3 #### osherove.com - [Minimizing unit Test Fragility – 8 features in Typemock Isolator to help](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html) - [Code excavations, wishful invocations, perimeters and domain specific unit test frameworks](https://osherove.com/blog/2010/3/19/code-excavations-wishful-invocations-perimeters-and-domain-s.html) - [Using TypeMock vs. Design for testability](https://osherove.com/blog/2006/9/27/using-typemock-vs-design-for-testability.html) - [JustMock and Moles – A short overview for TDD alpha geeks](https://osherove.com/blog/2010/5/25/justmock-and-moles-a-short-overview-for-tdd-alpha-geeks.html) [Previous lesson Static Forwarding on a real legacy app](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/static-forwarding-on-a-real-legacy-app/) [Next lesson Code Excavations and Domain Specific Test Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/code-excavations-and-domain-specific-test-frameworks/) --- title: "Code Excavations and Domain Specific Test Frameworks" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/code-excavations-and-domain-specific-test-frameworks.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/code-excavations-and-domain-specific-test-frameworks/" tags: [] author: "Roy Osherove" description: "Lesson 12 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Bonus tracks on advanced patterns), 54:14. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Code Excavations and Domain Specific Test Frameworks 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 3. Bonus tracks on advanced patterns Lesson 12 of 14 Duration: 54:14 [Watch on YouTube](https://www.youtube.com/watch?v=Cmzs3zc04lo) Roy Shows how to build a domain specific test framework using the idea os "[Code Excavations](https://osherove.com/blog/2010/3/19/code-excavations-wishful-invocations-perimeters-and-domain-s.html "Code excavations, wishful invocations, perimeters and domain specific unit test frameworks (osherove.com)")" ## In this lesson In a talk, Roy Osherove looks at code hosted inside a framework, such as a Silverlight control that cannot be created in a [unit test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)"), and at [Microsoft's Silverlight test framework](https://osherove.com/videos/2009/8/25/unit-testing-in-silverlight-silverunit-and-ms-sliverlight-te.html "Unit Testing in Silverlight - SilverUnit and MS Sliverlight Test Framework (osherove.com)"), which runs tests in the browser. He compares faking interaction points with an [isolation framework](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99 "Defining isolation frameworks (The Art of Unit Testing, 3rd ed., ch. 5)"), wrapping the system in role-based abstractions, and [excavation](https://osherove.com/blog/2010/3/19/code-excavations-wishful-invocations-perimeters-and-domain-s.html "Code excavations, wishful invocations, perimeters and domain specific unit test frameworks (osherove.com)"), where wishful invocations reveal [deep dependencies](https://osherove.com/blog/2005/8/23/issues-in-breaking-dependencies-for-unit-testing.html "Issues in breaking dependencies for unit testing (osherove.com)") to [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)"). Using the open-source [CThru framework](https://osherove.com/blog/2009/2/25/adding-method-missing-support-to-vbnet-using-ctru-and-typemo.html "Adding Method-Missing support to VB.NET using CTru and Typemock Open-AOP (osherove.com)"), he disables Silverlight constructors and methods one dependency at a time, which led to [SilverUnit](https://osherove.com/blog/2009/2/25/introducing-silverunit.html "Introducing SilverUnit (osherove.com)"), a domain specific test framework running tests in memory. ## Transcript 8,491 words [\[00:07\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=7s) Hi everyone. Today's presentation is going to be a very interesting for me, not necessarily for you. And it's because there's a whole new technique that that I've I've stumbled upon which I'm going to introduce and I'm going to introduce some patterns for u [breaking dependencies](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3 "Using stubs to break dependencies (The Art of Unit Testing, 2nd ed., ch. 3)") in frameworks where framework is actually a host is an envelope for the code that you're trying to write. A little bit about me. If you want to follow me on Twitter, that's my Twitter address. I'm I started a new blog called 5whys.com which is actually not about coding. [\[00:42\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=42s) It's about team leading and it's a whole subject which I think is very missing. So we in in everything that we do as programmers there's the technical side but then there's the people side and there are a lot of problems that come from the people side. So even if we if we all believe in [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1 "Defining unit testing, step by step (The Art of Unit Testing, 2nd ed., ch. 1)"), we can't a lot of times we're the only ones on the team and we can't we don't know how to convince other people or we cannot lead the team that that's under our control to do the stuff we believe in and team leadership is something that's missing and that's that's why I started a course about it and a blog about it and I think it's going to be the next wave in the agile development space not just technical. [\[01:23\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=83s) I work for a company called Typemock and we just recently released a free tool called Test Lint. So if you write unit tests in .NET and in Visual Studio 2010 it's a free plugin that will actually parse your code as you type it and will detect common errors. For example, when you have logic inside a unit test, it will actually flag it, give you a nice popup inside Visual Studio, tell you about it. It's extensible. you can write your own rules and again it's it's free and extensible. [\[01:54\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=114s) So this is my own little pet project. I think that's that if we are trying to teach other people to do the stuff we believe in that we need to give them tools to help them to do it. And I think that's that could be a step in the right direction. I'm also the author of a book called [the art of unit testing](https://www.manning.com/books/the-art-of-unit-testing-third-edition "The Art of Unit Testing, Third Edition (The Art of Unit Testing, 3rd ed.)"). And today I will be giving one free copy of that book. I will explain how you can get it later. I will be coming back here in July 19th to do a 5-day TDD master class with Iimea. [\[02:28\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=148s) So if you are interested there they actually have a booth right here. Feel free to talk to them about details. You can go and read about my book at [artofunittesting.com](https://www.artofunittesting.com/ "The Art of Unit Testing (artofunittesting.com)"). So today I'm going to talk a little bit about what cogs are. I think we all know the the problems that that we're facing. And I'm going to show several solutions to the untestability problem when we try to write code that's hosted somewhere. [\[02:59\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=179s) I'm going to introduce two new terms [excavation](https://osherove.com/blog/2010/3/19/code-excavations-wishful-invocations-perimeters-and-domain-s.html "Code excavations, wishful invocations, perimeters and domain specific unit test frameworks (osherove.com)") which is a new technique or it's not new but it's new for me and it introduces a new a new a new way of testing something. And it's a way to create what's called a domain specific test framework. And I'm going to show demos of these things as well. And I'm going to show how how we do that, how we try to solve the same problem today. If we have time, I'll do a little song about unit testing. [\[03:33\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=213s) But first of all, I want to show an example of what a cog in a machine feels like. And the example is taken directly from my own life experience of trying to write unit tests for something for a control in Silverlight. Is anyone here has anyone here ever looked at Silverlight related stuff? Okay, so about half the people here. Has anyone here ever tried to do unit testing on anything? Not just Silverlight, just unit testing. Okay, so that's the kind of crowd that I like. [\[04:04\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=244s) You like to raise your hands? That's always good. An example of a cog is something that to that you can't really just create a simple unit test for a complete box is a control built by Microsoft as an open source control that runs only inside the Silverlight runtime that is inside the browser. If we try to instantiate it in a simple unit test, we try to run this test, [\[04:36\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=276s) We will actually get plenty of errors that have to do with a lot of dependencies down the line. Just as a short example, this is the whole stack trace that we get. We try to instantiate this and then there's a constructor that's being called and a framework element as a base class and another constructor on the base class another constructor and at some point this whole thing is calling some other type by that's created as part of the Silverlight runtime called XCP imports jolt helper [\[05:15\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=315s) The point is that even though the control looks harmless it's actually like like the root of a tree. You can only see the top of it, but the roots go way deep because it inherits from the system. So just trying to to to create an instance of that object invokes multiple dependencies inside the system. So it's basically untestable because it inherits from the system. So there are different ways to test it, but unit testing is not one of them right now. [\[05:46\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=346s) There are integration ways of testing the same thing. And I'll show a way for [integration testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)") that problem. But cog structures are are the ways code can be tied to the system that's enveloping it. For example, a cog might inherit from an object from the envelope framework. What is an envelope framework? Silverlight. SharePoint is something that hosts your code. [\[06:19\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=379s) Windows workflow innet the CLR and Java runtimes are actually envelopes as well and you can actually replace both of them you can actually create your own envelope of the CLR you can actually host a CLR instance and actually make the system work differently so think about it a piece of compilable code is also a cog in a machine which is the CLR or in the Java runtime Visual Studio or anything that loads plugins is a host is an envelope that treats your code as part of it. [\[06:53\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=413s) But for plugins, there is a [testability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec1 "Why should I care about testability in my design? (The Art of Unit Testing, 2nd ed., ch. 11)") story because they have contracts which are well defined. So inheriting from an envelope object is very very common to be part of a system. Sometimes you don't have to inherit from anything but to get things done in the system you have to call a lot of static methods. You have to create a lot of instances of system types as part of your code. And sometimes you just have to implement interfaces from the system. And again, interfaces are okay because they are the equivalent of a contract which is fully replaceable. [\[07:29\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=449s) So you can replace the system when you have interfaces and they are the only means to contact the envelope. So I showed the example of just creating a simple control and the truth is that there is really no way that Microsoft could have found to create a real unit test for it. So what they did is they created a whole new test framework specifically designed for Silverlight. [\[07:59\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=479s) Now it's not a unit testing framework although they call it that way. It's an integration testing framework. It invokes the browser. It actually loads the browser instance. It runs the code inside the browser. Now, because everything runs inside the browser, everything is asynchronous. So, what happens is that your tests that kind of look like unit tests now have to know about asynchronicity. And that means that you have to use a lot of interesting attributes and function calls that are built into the framework that Microsoft created. [\[08:30\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=510s) For example, you have to put the asynchronous attribute on the test. You can put priorities on the specific test. Whenever you want to do something that has that is touching the browser UI or visuals or something like that, you can't just do it because the browser is running on a different process than the test. So, you have to incue it. you have to actually create a queue of actions which are incued inside the browser and are executed as part of the Silverlight runtime. [\[09:03\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=543s) So every action you would have done normally without threads such as creating adding a child to some test panel asserting something setting text on the control asserting that something is not null or whatever now have to be enclosed in a what's called an inq function which is part of the test framework and what it does the the syntax that you're seeing the the arrow actually means that the whole thing here is an anonymous method. [\[09:35\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=575s) It's basically a delegate inside the braces. So, it actually means run whatever is inside these braces later on in the browser in Q these things. Now, because these are all incued and I and this is asynchronous, I have no idea when the test is really complete and the browser never knows. So I have to also remember to do inq test complete so that the browser can actually shut down or the browser can stop waiting because my test will have to wait until the actual test in the other process finishes. [\[10:07\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=607s) So if I don't call this method now my test becomes stuck because the browser doesn't know I don't know when the test actually finished in the browser. So this is a horrible way of doing things. I think we can all agree that just learning the syntax and trying to understand whatever is written in this in this test it's practically impossible. It took me two days to find out that I forgot to do in Q test complete at some point. Ju just imagine >> get informed whether >> sorry >> does this tester even get informed whether the assertions [\[10:43\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=643s) >> does the test get informed whether the what >> whether the assertions >> whether the assertion worked. Yes, it gets informed. The framework actually will get back to you all the exceptions and it will inform you but all the exceptions are written in the browser. So you have to look at the browser. You have to be there as a person. You cannot run this as part of an [automated build](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec1 "Automated builds running automated tests (The Art of Unit Testing, 2nd ed., ch. 7)"). You actually have to be there sitting there watching the tests. Okay? And if if you see something red then means it's problem and your test will fail but all the results will be in the browser. [\[11:17\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=677s) There's a special [test runner](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_37 "The library, the assert, the runner, and the reporter (The Art of Unit Testing, 3rd ed., ch. 2)") in the browser. So there are other problems with asynchronicity. For example, because it runs in the browser, sometimes there are timing issues. So the tests, like Net likes to say, flicker. Sometimes they work, sometimes they don't work. Thankfully it's only like 5% of the time that they fail for timing issues. So that's great. That's perfect. That's exactly what you want, a test that only 5% of the time fails because that's a measurable [\[11:48\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=708s) Good thing. So when we try to to do unit testing against such a system and against such a cog or piece of code, we need to ask ourselves, does the system allow itself to be replaceable in some way? For example, the CLR is actually allowing me to replace the whole envelope. you can actually host your own CLR and run compiled code with a different behavior. For example, you can create a CLR that traces all the method calls. [\[12:20\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=740s) It's very simple to do once you know how to do it and you only do it once. You create that that envelope and you do it. So imagine the folks that created the CLR. That's how they tested it. That's how they tested that you can actually compile something that you can actually take the output and put it somewhere that you can check the output from and so on. If the system is replaceable, it means that you can either implement interfaces or you can easily handcode your own adapter code against the the new code. [\[12:52\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=772s) For example, if SharePoint was really easy to program against, I could say, you know what, it's a really good idea to take whatever code is trying to use SharePoint and wrap it with a role-based SharePoint model of your own which only has two, three, five methods or so and so on. But when you have a chatty interface into a system like you have to call the system continuously to get everything that you need with multiple methods that becomes a bit problematic because hand combing that stuff becomes a very big chore and [\[13:28\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=808s) And it becomes unmaintainable at some point. But for sure for simple interact interaction systems this works great. And the third option is to use isol is [isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec1 "Why use isolation frameworks? (The Art of Unit Testing, 2nd ed., ch. 5)") to [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") parts of the system just in an ad hoc manner. So that you can actually for this test just say that the system for this interaction point for that method will return a fake object. You don't fake out the whole system. You just fake out two three points in the system. So for systems that are replaceable, [\[14:00\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=840s) If we take the star here and the star represents the new code that we're trying to write and the the envelope system is in blue here. Our code needs to run in the system. Usually our code will not run alone. It runs inside other code that we already wrote for the system. So our code will interact with the code that we wrote which also interacts with the system. But any contract between us and the system because the system is replaceable is not really hardly defined. [\[14:33\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=873s) That is it's very easy for me as as the code. I don't really care if I'm working with the real system or not. I work as if everything is just fine. So the boundary or the perimeter I call this a perimeter because boundary is a bit of an overloaded word. Now, the perimeter of testing or the perimeter of understanding if I'm against the real system is right here in the interaction points. And I don't care if I'm in the real system or not. As far as I'm concerned, it's always a real system. As far as the code is concerned, that's only true for replaceable systems, systems that allow replacing. [\[15:10\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=910s) But we're not dealing with those kinds of systems because if we dealt with those kinds of systems, if we were to use a framework like JMock or [Rhino Mocks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5 "Current isolation frameworks for .NET (The Art of Unit Testing, 2nd ed., ch. 5)") or Typemock, you would be able to easily just fake out parts of the system where you're trying to interact with. For example, your code only calls methods in this part of the system. So I don't need to wrap the whole thing. I just wrap whatever method that this test is currently calling. [\[15:42\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=942s) When the system is not replaceable. What we used to do and what we a lot of people are still doing and definitely what's recommended in Steve's book is to actually detect roles in the system and surround your code under test with these role abstractions so that you don't actually talk to the real system, right? You just talk to those specific things that the system represents to you. So what does the parameter look like when you create your own wrapper or adapter system [\[16:16\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=976s) Against the actual code? So again imagine that this is our code. This is how we interact with the system and the white line is the line that represents the code that's wrapping the code. That is this is our rolebased interaction system. So to my code, I have no knowledge that Silverlight or SharePoint actually exists. The only knowledge that my code has is that the wide thing around here, whatever roles I need to talk to, they exist. [\[16:51\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1011s) So it's just a piece of pure logic. If it needs something from the system, it uses a specific role that gives it that information. So the code is purely independent. it doesn't actually have to run inside SharePoints tomorrow if we decide we move to a different framework. Now again this is great when you want to also look at the design of your system and it's great when you can do it in a how would I say when you do it in a in a in a time efficient manner. [\[17:26\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1046s) If it takes you a year to write that it's a bit of a problem. And the third and the the the third way to do it and the way that I'm going to show is called excavation or basically I I'm taking the term from ar ar ar ar ar ar ar ar ar ar ar ar ar ar ar ar ar ar ar ar archaeological type of work because as you're going to see what I'm going to do is I'm going to try to invoke a piece of the system see what the problem is just like you saw look at the stack trace [\[17:57\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1077s) Find the dependencies inside the system that have a problem which might not be the direct interaction that I need and and try to fabricate or fake out those specific dependencies which might be very deep inside the system and then I would continue to do another wishful invocation. What's wishful? Wishful means I wish if that if I just invoke this method nothing bad would happen. I can just invoke it in unit test and nothing bad would happen. It's wishful because I don't really know because it's part of the technique of excavating and finding the interactions of my code in the system. [\[18:33\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1113s) So if imagine if I get started testing something in Silverlight and I have no idea what the dependencies are, the simplest thing for me to do is to try to invoke the constructor of an object and see what happens. That's wishful invocation. Now you do this repeatedly and every time you fabricate an interaction, you actually close one loophole in the system. So that eventually you can get an interaction against an object that inherits from the system or anything but [\[19:04\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1144s) The system just works. So any invocation that we need actually just works. Just a what would a perime a parimeter like that look like? It looks very different than what I just showed where you would create a wrapper or an adapter because what happens is that if I try to create an instance of the the code, the code might get an exception way deep inside the system, maybe five levels down in an inheritance chain where some static constructor or something tries to load an XML file which doesn't exist. [\[19:42\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1182s) So I actually fabricate that specific piece of code which has nothing to do with the interactions against the real system. It could be five levels down. That means that I'm actually going down into the system and I'm creating a deeprooted u perimeter which is actually might have nothing to do with a specific test. It might work for a lot of other tests later. So I'm going to show a specific way of how I'm going to do it. [\[20:14\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1214s) So again this is taken from my specific experience of creating a Silverlight unit test framework. And what I wanted to do is I wanted to I tried to run the tests that I showed you that are based on the Microsoft test framework. And I tried to write these tests. It was horrible. And I I was I was not going to do that anymore. So I try to find a way using AOP aspectoriented programming to intercept the calls into the system and fake out any inputs any outputs from the system and so on. [\[20:50\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1250s) Now the way I'm going to do it is I'm going to use there are several tools that that that are able to do what I'm going to show. I'm going to use the tool that's the simplest for me and it's called it's a framework called [CThru](https://osherove.com/blog/2009/2/25/adding-method-missing-support-to-vbnet-using-ctru-and-typemo.html "Adding Method-Missing support to VB.NET using CTru and Typemock Open-AOP (osherove.com)") and it's an open source framework that's based on a commercial tool. So it's an open source framework that's based on the Typemock open AOP API which is the one of the tools that my company produces and what it allows it allows runtime interception into any system even if it's pre-ompiled. [\[21:24\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1284s) Now, of course, any aspectoriented program will will be able to do that given the ability to intercept compiled code and there are some frameworks that allow you to do it. the way I use the CThru to intercept parts of the system and in this case I'm just going to do it using a [setup method](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162 "Avoid setup methods (The Art of Unit Testing, 3rd ed., ch. 8)") because this is going to be true for all the tests is that I add a reference to specific DLL and to the type API and I and I add a specific aspect to something called a CThru engine. [\[22:01\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1321s) So the CThru engine is actually the engine that collects any entry points and allows me to decide what to do on any method call during the system runtime. That is any method call. I can intercept even calls to plugins in Visual Studio or anything else. Now the way you configure the CThru engine is by adding aspects to it which is just something which inherits from an aspect and I tell the CThru engine to start listening. [\[22:33\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1353s) Inheriting from an aspect is basically inheriting from the aspect class and overriding once one important method called should intercept. Now, should intercept takes an an info such as the method that's about to be called the name, the type name, and all that stuff. And for now, I just return true for everything. I tell the engine to intercept everything. And of course, that means it's going to be much slower. Those tests are not as fast as unit tests, but it's good enough for me to get started because this is the excavation part. [\[23:09\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1389s) I'm just trying to see what's going to happen. And now I can override specific methods. For example, I can override constructor behavior throughout the system. And I can say for any constructor in the system, if the type name of of the constructor in contains the dependency object type, then the method behavior will be skip the actual method. Don't really don't really call that method. Okay. And for any method behavior in the system, if the type name of the method is dependency object, [\[23:41\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1421s) If if it's not dependency object return, so I only care about something that inherits from dependency object. What is dependency object? It's basically the thing that my control inherits from. If we look at the stack trace that I showed earlier, you will see that here in the stack trace, there is a constructor for a base class in dependency object. And this constructor is called for any control that's created in Silverlight. And eventually this constructor calls a whole bunch of things inside the system. [\[24:12\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1452s) XCP import scrap whatever anything here. So I'm just going to disable that specific constructor. So I'm looking for a specific type and I'm disabling that constructor. I'm just going to show that for a second and I'm going to show what happens. So I'm going to run again this same line of code with the CThru engine running. And [\[24:45\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1485s) What's going to happen is that I'm going to get a different exception. Now, how do I know it was running? Because inside the aspect, I actually wrote to the console. I said skipped a constructor. You will see that the stack trace looks very different. Now skip ctor is basically this piece of code here if type name is dependency object write line the method name and skip. So now this is the first step in my excavation and what I find out is that I disabled the constructor but there's still a problem. [\[25:17\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1517s) There is still another dependency. So that's the second dependencies that I'm finding and what I'm finding is that by default someone is calling control set default style key. Where is this being called? It's being called from the actual code under test. So I so given that this is code that I want to test. What happens is that whenever you try to set values inside dependency objects they actually call another dependency in the systems because values in Silverlight and WPF in.net always use static dependencies and save the values somewhere else not especially inside the object. [\[26:00\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1560s) This is what's called dependency properties. And dependency properties are nasty because they're all static. So any call to a regular object actually instantiates some static property that has a lot of instantiations of bad stuff. Now I just want to disable the internal stuff. Now set value internal is about three levels deep from the original interaction. But I'm going to disable anything that is set value because I don't care about really setting values internally. [\[26:30\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1590s) I'm just faking out the system so that I can instantiate an object. We're going to talk later about what it means to actually mimic the system behavior, but for now I'm just stubbing everything. So I'm going to use this piece of code to say only work on dependency objects. And I can say for now or and that's another dependency which I'm going to show in a second. If the method name is set value internal then skip that method and continue and then I try to run the same test again. [\[27:09\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1629s) So now skip ctor skip set value internal and I get a third dependency. Now this third dependency is from something called add loaded. What is add loaded? Basically what happens is that someone is calling dependency object addeventlister which gets native object which basically could not find filer assembly XML which is a different Silverlight XML assembly and [\[27:40\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1660s) At this point I don't even care. I just want to mute this problem. So again, I'm going to add a third part to my excavation series and I'm going to add the method name for add event listener and I'm going to say don't do anything when someone tries to add an event. So I run this test again and hopefully now everything should be okay. So you can see I skipped all this stuff and now I can actually create an instance of a Silverlight object. Now, of course, this is all a big lie because I create the instance, but the instance is actually might set some values internally, might add some events. [\[28:18\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1698s) It really has no behavior right now. So, what's left for me is to actually not just override and mute stuff. I now need to add some system behavior that looks like the real system. So I could actually override set value and say when someone tries to set value on the problematic system just save it in memory with the value name so that when someone asks for the value back you save it and you give it back. So I act like the real system when someone adds an event listener you take the delegate and you return it later [\[28:49\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1729s) So that I act like the real system but I don't depend on the real system. So that was a simple excavation and to find the dependencies of an object and again this is why the perimeter looks like this because some of the stuff that I am actually replacing is not very close to the object. It could be three five levels down. I could maybe find very low-level static constructor that calls the system and sometimes I just disable a specific interface directly against the object. [\[29:24\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1764s) So the parameter looks very different and of course it works because I have a full framework that's called [SilverUnit](https://osherove.com/blog/2009/2/25/introducing-silverunit.html "Introducing SilverUnit (osherove.com)") that's built on the same the same idea and this is what test look like for SilverUnit after imagine about a 3-day iteration where I at some point I also create a simple API to test verifications of autocomplete box. So what does the framework look like? There is an you you basically write a simple unit test. [\[29:58\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1798s) You put an attribute on it. You create instances of objects. You can set their values and you can check you can assert on their values back. For example, you can check that in Silverlight you you have custom logic that says if someone gives you an an invalid minimum prefix length, it automatically resets to the next valid one. That's that simple logic behavior. the piece of code that that exercises this piece of that's exercised by this test [\[30:28\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1828s) Exists here basically let's see this this is the piece of code that I'm actually testing now this piece of code is invoked in an event that's driven by a static property setter and when I have enough AOP capabilities I can definitely mimic that behavior and invoke any code by the user as if I'm the real system. So I'm able to test simple code [\[31:01\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1861s) And this is an example of how I can use this the framework to override the idea of XAML. What is XAML? Who for those who don't know Silverlight and WPF all controls and visual stuff is also laid out in a XAML file which actually is kind of like an HTML that says what is the visual looking like and to whenever you try to create something it loads tries to loads the XAML for that object as well but I didn't want that dependency so instead of letting the XAML tell me all the layout and internal controls. [\[31:40\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1900s) I'm actually using my own framework to set and inject controls into the parent control that's under test. So I can check all the logic that I need. No XAML included, nothing. This is a pure unit test. Everything runs in memory. No file dependency whatsoever. I can also check interactions against the system. When you call on apply template, you assert that visual state was changed to normal. This is a piece of logic that says when the Silverlight control is just created, it moves to a normal state. [\[32:15\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1935s) Now, if you don't know the Silverlight object model, don't worry. It's just an example of something that is actually this is an assert that is specialized for the system. And this assert what it does, it actually collects values that were sent into the system. So whenever I need to, I can actually ask if something in the system was called. So the whole system can be used as one big [mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") if I really need it. By default everything is fake and if I need to I can always ask the system something. So every value is saved. [\[32:46\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1966s) Now there is no setup code that does all this stuff. The setup code is actually exists in this attribute. Okay. So imagine that I'm doing the same setup of overriding using aspects and all that stuff for all the the tests that you see here. Here's the third example of I showed of what a Microsoft test would look like. [\[33:17\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=1997s) Let's see. This is the Microsoft test framework. This is a test that checks text completion via text property. And it does all this stuff, this horrible stuff. I'm going to show you what this test looked like. as a unit test in SilverUnit. This is the same test. When you set the text box, the autocomplete box is updated. I call is enabled. I set the selection start. I set the text. [\[33:48\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2028s) I actually let u make the control fire an event. So using SilverUnit I'm actually faking event invocations so that I can trigger this is actually the act part if you think about it the whole thing. So I'm triggering an event with with a piece of fake event arguments. I'm actually making a fake event argument type because part of the system actually the constructor for text changed events is actually internal. [\[34:20\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2060s) So I can't really create it publicly. So again, SilverUnit and interception comes to my aid in this case, but I can actually fake event arguments into the system. And these are the asserts and this all runs in memory. And of course, you can add some more stuff into the framework. For example, you can add timing and reporting and all that stuff. So these are the three tests that you just saw and they all run inmemory, no problem. And again this is specifically for writing unit tests inside that system. [\[34:53\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2093s) So some more important questions that we have are first of all what what are the three types of isolation for a specific cog in a machine. The the simplest one on a replaceable system is interaction based where you use frameworks like JMock and so on to create a parameter that's only partial to the code under test. So the code only interacts with these functions. So I only fake them out. [\[35:24\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2124s) I might have found out very easily that I just need to fake these interactions. So I fake only them. There's the role-based contract which is much cleaner. The design is much easier to understand. It might take a long time to create. I'm going to talk about the differences very soon. You can definitely create this with TDD and you would get this automatically. There's the dependency based or the one that I just showed the excavated one which looks different. [\[35:56\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2156s) Now the the interesting thing is or the the big surprise for me is is that I was really afraid that if you try to create a perimeter that that looks like this because you're actually faking out something that you don't own, you're actually faking out part of that system is that it's going to be very fragile because you have no control of that system. And because you're faking out stuff that's private or internal, then it's more likely to change. But the surprise was that that wasn't true at all for that system. [\[36:31\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2191s) In Silverlight, I started SilverUnit when Silverlight was the version one. Right now, Silverlight version 4 is coming out and I didn't need to change one piece of code in the framework. And I think the reason is is for big systems that host stuff like that your your own cogs if you will is that the system is so heavy is that it's not likely to change at all. And this is just just a conjecture. It's I I don't I don't know if it's true, but it feels true because that's my own experience. [\[37:03\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2223s) The system was very very not changeable in terms of the way Microsoft wanted to change things because it's already a monster and monster systems don't change internals like that. So I think that rolebased is very robust. Interactionbased is not as it can be very brittle because the interactions against these interfaces from your own test code keep changing. This is code you own. So no problem there. You have full control of that code. This is actually very robust as well or so it seems for me because [\[37:38\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2258s) The interactions against the system can be much closer to the actual parameter. So even if the interactions with the real system change because what I do here is in such broad strokes I just mute whole types whole functions I just do everything so if I need to mute something I will mute all the static methods in that type I don't care because it's all internal then it's it actually doesn't care what interactions happen against the system at some point so it's very robust and again because the code internally in the system doesn't really change in the in the in the Silverlight framework [\[38:15\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2295s) Then I don't need to change the actual SilverUnit framework as well. So it's robust both in terms of interactions with the external system and both in the idea of faking stuff in that external system. So excavated parameters seem pretty robust and I say seem because this could be not true for other systems but it feels like it would be true for systems like SharePoint. It feels like it would be true for systems like ASP.NET where you can someone actually created using CThru again their own ASP.NET net testing utility or API [\[38:55\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2335s) Which intercepts HTTP runtime related calls and works the same way and he hasn't needed to change that in a year. So if the host system deep internals don't seem to change at all over versions. So creating deeprooted parameters for that for for testing could also be robust. They could be maintainable because you don't need to maintain them. So some more interesting points one of some one of the things that I need to do is I needed to cancel code that was asynchronous in the system. [\[39:30\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2370s) A lot of things in the system actually created timers and expected those timers to fire at some point in time. So I I intercepted those timers and I invoked that function or that delegate immediately. So all timers in the system canvoke on the same thread never on different threads. So the whole test is fully synchronous. I had to mimic a lot of system behavior like event subscription. I had to save a lot of values. And everything in the system is saving values as well so that I can actually test that something was called because a lot of times your code that lives inside other people's system their [end result](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)") is calling that system. [\[40:15\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2415s) For example, the logic says when a control is being clicked, it tells the system to change the visuals. That's all it does. And the system will take care of the rest. So that's an interaction boundary and I need to test that. And the idea of faking whole types, this is very different from regular testing where in an ad hoc manner you fake that point and that point and that point. When I do excavation, I mute whole types. I say, "Oh, I see something is calling Xcp imports.static method." I will fake everything in XCP imports. [\[40:52\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2452s) I don't care about that type because it's so deep down. I can use these broad strokes to do it. The process was interesting as well because all these wishful invocations didn't just create my tests. My tests actually helped create my own domain specific test framework. And I think that when you have cogs inside machines and you use this the excavation stuff you will always or it looks like you will always get your own domain specific test framework out of it. [\[41:23\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2483s) Now you create it basically once and you can reuse it. It's very reusable. And the tests are very robust. They're very readable. The end result is very readable, very simple to do and suddenly you have full control of that system. But the tests have no idea that they're running in a different system because what actually happens is the tests actually do run in the external system. We act we just disable parts of that real system. Some of the tests might actually be a form of integration tests because they're actually re using real parts of that external system up to the point down below where we removed part of that or muted some function. [\[42:09\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2529s) Tools that you can use to create these parameters. PowerMock in Java will allow byte code manipulation. Anything that allows byte code manipulation or IL manipulation will work. In .NET there is a thing called [Moles](https://osherove.com/blog/2010/5/25/justmock-and-moles-a-short-overview-for-tdd-alpha-geeks.html "JustMock and Moles – A short overview for TDD alpha geeks (osherove.com)") which is free and relatively new and it might be a good idea to try to do that. So Typemock is not the only way to do it in .NET as well. And that's basically what I have. Mostly I'm raising this issue because I want to hear about your experiences if anyone here has ever done something close to this or they try to intercept something in a real system. [\[42:48\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2568s) There is I know of maybe just one other example and again it's someone who uses the CThru engine as well. So, I'm not sure if this is a real pattern or not, but, someone told me that it only takes three times to look at that in the wild and say it's a pattern. So, I'm just I just need one more. Just one more. Are there any questions? Anything? [\[43:18\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2598s) >> Yeah. >> So, you got to framework. What about do they help are they part of this kind of >> so the question is do aspectoriented frameworks in .NET help this well aspect or aspectoriented frameworks in .NET most of them don't support manipulation of byte code on external systems just in code that you own for example I also use PostSharp inside our products but the problem with post is that it only works when you compile the code that you own And here I'm actually intercepting code that I don't own in Silverlight which is already compiled. [\[44:01\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2641s) So PostSharp will not work there. It only works for runtime AOP not compile time AOP. >> Yeah. Any other questions? Yeah. >> I've actually been trying to test SharePoint workflows with a lack of success using Typemock and I started to look down the CThru routes but sort of peted out on it. And the point test because it's a workflow. I can set up all of the properties for it, but then I've got to force it to iterate to move through the workflow. [\[44:33\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2673s) >> Okay. >> An awful lot of work to simulate the effect of the workflow engine. >> so the question was that you were trying to do kind of the same thing with CThru in SharePoint workflows. But at some point you stopped because it was a bit too complicated. >> you ran out of time. That's that's definitely possible. It did it wasn't a trivial attempt to do SilverUnit. It actually was an interesting exercise to see what h what would happen. So I think first of all that doing the same thing for SharePoint workflows is totally possible where you mimic not the whole workflow just the basic stuff that you need to test. [\[45:12\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2712s) For example, if you need to test a specific thing that runs inside a workflow, you just want to test that the logic of where it should sit is true. I'm not sure. I haven't tested any kind of workflows and I'm not an expert in SharePoint workflows. >> What I've tried to do in the past is if I've writt a custom activity, I'll test that independently by just injecting values. But if the idea was to try and test a workflow that the business logic was flowing so integration aimed towards fitness or something in the end. >> Okay. [\[45:42\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2742s) So you wanted to run your own workflow engine which was fully estable. I think that's possible. >> You think that is possible? Yeah, I think that's fully possible given the fact that the workflow engine will take configuration of what to run from an external file. You don't need to intercept the whole engine. You just need to incept the engine in the correct points to inject the values of what to run. The the problem is finding those points. That means a lot of mcking around with Reflector maybe or just doing a lot of wishful invocation to see what would happen. So I think it's it's it's it's a powerful technique. [\[46:15\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2775s) It takes dedication to do. Once you do it you've actually created another domain specific test framework for for SharePoint workflows which you can reuse and you can be so if you wanted to be an open- source wizard or something and you know be cool to your friends you say I just created my own domain specific test framework okay buy me a beer or something there should be like a shirt or that so I think it's possible not trivial yeah it wasn't trivial to create SilverUnit it's just trivial ble to show it in a demo which is always true. [\[46:50\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2810s) Any other questions? Yeah. >> This reduces your confidence in tests because you're playing about with internals. You're not always 100% sure that the system is going to behave the same way that it does in the real system. >> So do I find that I'm less confident in the tests because I'm actually faking parts of the system. So in real life it would behave differently. Well, I don't have any problem with that because for unit tests I'm only testing the logic. So I can do it in TDD style. It doesn't mean that I won't do integration testing actually run it as part of the browser. [\[47:22\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2842s) Okay, it doesn't mean that it's in instead it's just as an added way. If I wanted to do TDD on a Silverlight control now I can do that. But I will always check it on the real system. No such thing as just doing unit tests on a system and that is what gives me the confidence in the integration part of the system. Unit versus integration will always come together. I don't think that you can always any any time replace one with another unless you're willing to give up either confidence if you're willing to give up integration testing or you're willing to give up early early implementation failures in TDD when you give up unit testing [\[48:02\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2882s) Okay yeah any other questions anything at all yeah >> so from what I understand this is kind of a work to make test >> this is a workaround to make Silverlight testable. This is the only workaround that I could find because you inherit from the system and that's one of the only cases where I think and Steve correct me if I'm wrong. There is no way around that even if you create a subsystem if the object that you want to test inherits from the system you cannot wrap around that because it's part of it. [\[48:36\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2916s) So I think that was real problem I couldn't work around Silverlight runtime because the object doesn't call methods on the system it inherits from the system. Is there anything if you kind of I know it's a bit of another question but if you design now do you think they could have made it more testable opened it up more >> if they were designing Silverlight now could they have made it better in terms of testability? I think that well that the only way to do that was to remove inheritance so that whatever you try to create only implements interfaces in instead of real inheritance and that would have worked so it's possible and but the the thing is that every framework like Silverlight or visual framework eventually you will want to have a base class in the framework you can have 10 interfaces but at some point one of the de developers will say you know But we have all these interfaces and everyone always wants to implement that interface with the base class. [\[49:34\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=2974s) Everyone. So let's create a base class for those people. Let's not be jerks, right? Because they want it to be more usable. So the usability aspect is actually hindering the testability aspect. I think now again this is just a conjecture. Because I I didn't design Silverlight. I don't know what other stuff they were thinking about when they were designing it. But definitely there are a lot of problematic testability stuff and they needed to make a lot of that work because of XAML and dependency properties and the way Silverlight and WPF work which is pretty amazing and they made a lot of hacks or workarounds and created a whole new pieces of not notions in programming in the Silverlight object model to make all that stuff happen. [\[50:21\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=3021s) So, I don't know if they could have done it any better for testability. Maybe just in terms of design, but I think testability would still suffer. Any other last questions? Okay. So, there is time and we're going to do a little song. And for doing the song, I'm going to I'm going to need one volunteer to help me with the slides. >> Yes, sir. What's your name? >> Sorry. [\[50:52\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=3052s) What? >> More and near. >> More near. >> Yes. >> More near. Okay. Please go up. Can you give give your hand for more? >> you know what to do, right? First of all, don't touch anything. >> Okay. I I want to explain what I'm going to do here. I like to to to write songs about my experiences as a developer. And before we do the song, [\[51:22\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=3082s) Let's test out your skills. Okay? So the the point is every time I finish to sing the line, I finish the line, you press space. That's it. Okay? Are you sure? Okay. This is a test line. Looks like you're doing just fine. It's time for a song of mine. Okay, that's very good. So, now that we know that, we have a passing test, I want to sing a song based on a true story. [\[51:56\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=3116s) Now this, was a company that I used to work with a long time ago. And, it was a chaotic, problematic company. And nothing worked. And it got to the point where customers had a real problem with the stuff we were shipping. And this is a song about that company. Okay. Go. Our client likes to change his mind. [\[52:50\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=3170s) It all comes crashing down in flames. But we are knocking on the client's door. I think we got it. Knock knock knock knock knock knock knock knock knock knock knocking on the client's door cuz it worked in my machine knocking on the client's door [\[53:43\]](https://www.youtube.com/watch?v=Cmzs3zc04lo&t=3223s) And our culture looks like one big mess. But never mind, we're still knocking on the client's door. Yeah, I think this time we got it. Knock knock knocking on the client's door cuz it worked in my machine. Knock knock knocking on the client's door. But he doesn't trust us anymore. Thank you very much, guys. ## Related - [Code excavations, wishful invocations, perimeters and domain specific unit test frameworks](https://osherove.com/blog/2010/3/19/code-excavations-wishful-invocations-perimeters-and-domain-s.html) · osherove.com Roy's written write-up of this talk's ideas: code excavations, wishful invocations, perimeters and domain specific test frameworks. - [Introducing SilverUnit](https://osherove.com/blog/2009/2/25/introducing-silverunit.html) · osherove.com Introduces SilverUnit, the in-memory Silverlight test framework that came out of the excavation work in this talk. - [Unit Testing in silverlight land with Typemock Isolator](https://osherove.com/blog/2008/12/27/unit-testing-in-silverlight-land-with-typemock-isolator.html) · osherove.com How Roy got Typemock Isolator faking code inside Silverlight, the first step toward the approach shown here. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Defining isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99), ch. 5 - [The Art of Unit Testing, Third Edition](https://www.manning.com/books/the-art-of-unit-testing-third-edition) - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [The library, the assert, the runner, and the reporter](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_37), ch. 2 - [Avoid setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162), ch. 8 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19), ch. 1 #### The Art of Unit Testing, 2nd ed. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Using stubs to break dependencies](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3), ch. 3 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1), ch. 1 - [Why should I care about testability in my design?](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec1), ch. 11 - [Automated builds running automated tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec1), ch. 7 - [Why use isolation frameworks?](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec1), ch. 5 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 - [Current isolation frameworks for .NET](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5), ch. 5 #### osherove.com - [Unit Testing in Silverlight - SilverUnit and MS Sliverlight Test Framework](https://osherove.com/videos/2009/8/25/unit-testing-in-silverlight-silverunit-and-ms-sliverlight-te.html) - [Issues in breaking dependencies for unit testing](https://osherove.com/blog/2005/8/23/issues-in-breaking-dependencies-for-unit-testing.html) - [Adding Method-Missing support to VB.NET using CTru and Typemock Open-AOP](https://osherove.com/blog/2009/2/25/adding-method-missing-support-to-vbnet-using-ctru-and-typemo.html) - [JustMock and Moles – A short overview for TDD alpha geeks](https://osherove.com/blog/2010/5/25/justmock-and-moles-a-short-overview-for-tdd-alpha-geeks.html) #### artofunittesting.com - [The Art of Unit Testing](https://www.artofunittesting.com/) [Previous lesson Testing Legacy Code with Typemock Isolator Deep Dive](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/testing-legacy-code-with-typemock-isolator-deep-dive/) [Next lesson Testing Complex Validation Knowledge using Extract & Override](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/testing-complex-validation-knowledge-using-extract-and-override/) --- title: "Testing Complex Validation Knowledge using Extract & Override" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/testing-complex-validation-knowledge-using-extract-and-override.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/testing-complex-validation-knowledge-using-extract-and-override/" tags: [] author: "Roy Osherove" description: "Lesson 13 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Bonus tracks on advanced patterns), 43:35. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Testing Complex Validation Knowledge using Extract & Override 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 3. Bonus tracks on advanced patterns Lesson 13 of 14 Duration: 43:35 [Watch on YouTube](https://www.youtube.com/watch?v=fKuiDFP9U0g) Roy shows how to test and complex validation method with refactoring. ## In this lesson Roy Osherove explains how to test validation logic that combines many rules, using a password validator, by testing each rule separately from the logic that combines them. He introduces [extract and override](https://osherove.com/blog/2012/5/16/test-driven-validation-logic-with-extract-override.html "Test Driven Validation Logic with Extract & Override (osherove.com)"), also called the [test specific subclass pattern](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95 "Partial mocks (The Art of Unit Testing, 3rd ed., ch. 4)"), with a testable subclass that overrides the [current time](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec5 "Cross-cutting concerns injection (The Art of Unit Testing, 2nd ed., ch. 7)") so a backup check does not have to wait seven days. He then writes a validator test first, with flags in a testable validator that set what each rule returns, and [tests a single rule method directly](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_160 "Avoid testing private or protected methods (The Art of Unit Testing, 3rd ed., ch. 8)") using the [InternalsVisibleTo attribute](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6 "Overcoming the encapsulation problem (The Art of Unit Testing, 2nd ed., ch. 3)"). ## Transcript 4,409 words [\[00:04\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=4s) Hi everyone, my name is Roy Osherove and this is a short video that I'm doing about writing complex logic with complex business rules using [test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)"). The reason I'm doing this video is first of all so that I don't forget and second so that I can show it to students of mine during courses that I teach. And you can find out more about me by going to my blog at ISerializable.com. And this is also going to be part of my book which is called [the art of unit testing](https://www.manning.com/books/the-art-of-unit-testing-third-edition "The Art of Unit Testing, Third Edition (The Art of Unit Testing, 3rd ed.)"). [\[00:36\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=36s) And this is an upcoming Manning publication which should be up in about I don't know 5 to 10 years. In any case, you will soon be able to download that book online through manning.com. And if you want to know more or get notifications or even just download the first chapter of the book right now, you can go to the [artofunittesting.com](https://www.artofunittesting.com/ "The Art of Unit Testing (artofunittesting.com)") and download that chapter and get notifications. [\[01:09\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=69s) Now, the the the type of scenario that I'm speaking about right now is a very basic, you know, run-of-the-mill validation constraint logic type of scenario. It's the those kinds of scenarios where you have many rules and you have this big maybe function that checks all these rules and combines them and if depending on some convol logic it returns true or false or does something [\[01:39\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=99s) And a lot of times this is part of validation process in many applications. So the the canonical example that I can think of is password validation function which returns true or false if something is valid or not. And there you know you can have a lot of rules for password validation. For example a minimum number of characters to have digits and so on and so on. Now of course you can use maybe some regular expressions to test these kinds of things. [\[02:10\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=130s) But you know sometimes regular expressions are just for testing the test the text. What if your application needs to test something that is not pattern based? You want to make sure that this is done as well. So you want to make sure that all this logic works. So there are different challenges to testing this kind of function. First of all you need to understand that there are two kinds of tests that you need to to to write for this sort of logic. The first of all is that that you need to test the individual logical constraints. [\[02:45\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=165s) For example, you want to know that if there are maximum number of characters that are exceeded, you want to know that something failed. So you probably would write a separate function and test it out that receives an input and returns true or false whether it passes or not. So you would probably write a different function for each rule. And then there is the one layer above which is the logic that uses all these small constraints and combines them to give one single result. [\[03:21\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=201s) So that's the logic that has all the if statements and it says well if there are maximum number of ch characters characters or there aren't any of these and this is not true then do something else. Now the main challenge is that once you know how to test these kinds of constraints is to write in testdriven development. So I'm going to show a demo of how you can actually write in a test-driven manner this kind of logic [\[03:53\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=233s) Using tests that fail first. So here's an example of the validate function on a class and this is this is the hierarchy of how the validate function will work. This is how I want it to look or this is what I have in my mind when I think about it. So you'll notice that in the upper part here the validate function is merely using all these small functions underneath. Now each of one of these methods or functions [\[04:25\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=265s) Is a rule on its own. It does a very simple thing and it has its own logic and this is the complex logic that I would like to test. However, I want to make sure that it's tested and I'm writing it in a test-driven manner. So if I spoke earlier about the two kinds of tests, you'll note that I basically will I'm going to write a test or many tests for the validate function and its logic, but I'm going to write separate tests for the has at least set six characters and so on and so on. [\[05:00\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=300s) And the tests here are going to pass or fail independently of the tests here. So even if has at least six characters its tests are going to fail the validate function its own tests might still pass because the logic here still works. So this is basically not very much different than separating dependencies in a regular TDD application TD written application just imagine that this is actually a web service call. [\[05:36\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=336s) So even if the web service doesn't work, I still want to make sure that my interaction with the web service here still works. So this should pass even if this fails. And how do I do this? Well, usually the what happens is that the pattern in the code has to look similar to this. The code uses all these functions and the functions returns true or false. [\[06:06\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=366s) And combining these values use during the test and telling those functions what to return can actually make us test validate separately. So here's an example. We are going to write a test that uses validate but it sets up the the the sub methods here to return the values that the test would like to return. So in our test the scenario would be if the password does not have a digit inside it that is this method returns false [\[06:43\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=403s) And even though all these other methods return true u the valid the validate method will return false to the test. Now, this is interesting because if you write test-driven development, you might not actually have this method or this method or this method. You might just have this method to test on, but you still want to make sure that in the next tests, the previous test is still going to to pass. So this will probably make more sense once we get into the code [\[07:19\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=439s) But we are going to go through this scenario and use test-driven de development to write it. Now to understand that we need to understand a a very powerful technique that we're going to use during our testing so that we can actually control these values. There has to be some way to control these values to that our test says well this will return true and this will return false. And why do I want to control these values for my test? [\[07:49\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=469s) I mean why shouldn't my test just give an input to validate that passes this but does not pass this? Well, the answer is that sometimes to the input to validate by the end of the production code is going to be very very complicated. Just imagine that some of the requirements here may be very very powerful such as the inputs have to be defined in a certain way, have to be of a certain size and so on and so on. [\[08:19\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=499s) So I would want to control them even though I don't want to actually run this code. I just want to simulate the fact that has digitic returns false. So my test needs to simulate that. And to do that, our test is going to have to create a class that inherits from the class that contains all of this. So if I'm going to actually use some drawing tools here. [\[09:18\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=558s) So the technique is called [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)"). If you're interested in learning more, there's a great book called [working effectively with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226 "Read Michael Feathers’ book on legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") by [Michael Feathers](https://osherove.com/blog/2009/8/18/ndc-video-michael-feathers-working-effectively-with-legacy-c.html "NDC Video – Michael Feathers – Working Effectively with Legacy Code (osherove.com)") and there he explains this, but this is also called the [test specific subclass pattern](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4 "An object-oriented partial mock example (The Art of Unit Testing, 3rd ed., ch. 4)") if you read the xUnit Test Patterns book which just came out. So the technique basically says that we're going to create a subclass of the class under test and then overwrite each of these functions [\[09:51\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=591s) And return whatever values we want. So let's see a demo of that and then continue. So, we're in Visual Studio and I just want to show you picture of my son It was born December 28th, 2006 and I love him very much. So, now he's in the video. In any case, here's my code for the book, The Art of Unit Testing. [\[10:23\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=623s) And this is everything I have right now. And I'm going to use this solution to show the idea of extract and overwrite and the test specific subclass. So let's add a class that is depending on time so that we can test it and see how we can test it. Let's call it my timebased class. Okay. I'm going to also use a a program called Keyboard Jedi. [\[10:55\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=655s) And the idea about Keyboard Jedi is that it will show any keyboard shortcuts that I'm using inside Visual Studio. I'm also going to use ReSharper so that if you see me doing something like this, you can see that I clicked alt plus enter to show the menu that you're seeing right now. So this is part of ReSharper. I'm just going to optimize the uses here. Let's do a public class [\[11:26\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=686s) And I'm going to write one simple method called public string get [current time](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_64 "Stubbing out time with parameter injection (The Art of Unit Testing, 3rd ed., ch. 3)") to see that it's actually get current time. And well, let's just say that my method is going to be like this. [\[12:03\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=723s) So the method I want to write is a method that maybe is used for backup. And so the method should tell me if a week has passed since the last backup. So let's write a property let's write a field let's say date time. Now the date time is we're going to use system day time to say [\[12:33\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=753s) Last backup and let's create a property. That's the last backup. And let's also do something like public Shoot should [\[13:03\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=783s) Back up now. Let's return false. Well, let's return Let's daytime dot now subtract last backup is [\[13:35\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=815s) In days is bigger than seven. So if more than seven days have passed since the last backup, it should return true. Now, how can I test this method? So, let's try to write a test for this method. Let's add a new class. Let's call it and since this class is called my timebased class, let's call it my timebased [\[14:06\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=846s) Class tests. Now, this is a test class. So it's going to be public and test fixture and let's write a test here. Now in my test I'm going to write three parts. The first part is going to be the method that I'm testing. So should back up now is the name of the method that I'm testing. [\[14:38\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=878s) Scenario is less than 7 days away returns false is what I'm expecting. Okay. So, how can I test this? So, the first thing I'm going to do is I'm going to refactor the class because I don't want my test to have to wait seven days. So I'm going to actually write a new class here called testable [\[15:09\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=909s) My timebased class which inherits from my timebased class. Now the reason I'm doing this is so that I can overwrite some stuff. But what do I override? First I'm going to get the current date time and convert that into a method call. So get time now [\[15:40\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=940s) And let's make it protected and make it virtual. That way we can override that in the class in the testable class. So, what I'm going to do now, I'm just going to override my get time now and say return current time. [\[16:12\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=972s) And what's current time? It's going to be a field called current time. Let's make it public. What else? So now I can use my actual testable timebased class. Testable timebased class backup equals new testable timebased class. Now I'm going to tell backup that the current time [\[16:44\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1004s) Equals new date time. The year is 20 The month is one, the day is one. That's okay. Now the thing is since this overrides the behavior and actually in the xUnit Test Patterns book, this is a variation of the pattern. It's called behavior modifying subclass which is pretty smart. [\[17:19\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1039s) What we're going to do is in the test we just told it what the time is. And now we're going to say backup should back up now. [\[18:03\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1083s) Result or let's call it shoot backup now. And I'm going to assert is true on the backup now. So let's see. Here is a test that should actually say well okay this is wrong because my test actually says has to be less than seven days. So has to be is false and the new day time is [\[18:43\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1123s) Okay. Okay. So we have to tell the backup here. Backup backup last backup equals new daytime and let's say 20 and 1 and the current time will be 200 and five. So back up now should actually return false. [\[19:15\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1155s) Okay. So current last backup is a standard property. So you can see that in the production code we would actually be using the real date time. But in the tests, we're actually getting getting the the the time that is under the control of our test. So this is called behavior modifying subclass. [\[19:48\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1188s) By overwriting the method, I just change the behavior of the class under test. Therefore, I can override time. I can make time stand still and my test will always run. Let's write the opposite test and see that it actually works. Should back up now more 7 days array returns true. [\[20:19\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1219s) So let's say eight or actually nine. This should be as true. Let's run all these. And this is actually an addin called TestDriven.NET that I'm I'm using and I'm running it here. You see two tests have passed. And that's it for now. Let's go back and actually see how we can use this technique [\[20:51\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1251s) To catch complex validation logic. So that was a demo. Let's take a look at what we're going to do now that we know about extracting override. So, we're going to write a password validator class that has all these complex rules and we're going to write a test that uses a validate and it's going to have various virtual methods that we're going to use and we're going to actually override these virtual methods in our test and do in a test-driven manner. [\[21:26\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1286s) So let's see what that looks like right now. So let's write our validator from scratch. So I'm going to actually write a class called validator. But my first test is actually going to be on a method called is valid that takes a password. Now I'm actually testing it on the logical level the one that uses the rules. [\[22:01\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1321s) I'm not testing the actual rules right now. just the fact that the rules are being used correctly the first and that means that I'm checking checking is valid when rule which is called at least six characters is false then it should return false [\[22:31\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1351s) That means all the other rules return So what am I what am I starting with? I'm going to start from the actual testable validator class. Testable validator TV equals new testable validator. And I'm going to make it compile soon, but let's finish the test first. TV. And I'm going to say set all flags [\[23:01\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1381s) To true. which is my way of saying I'm only testing one rule right now. You'll see that it's a very simple concept. Next, I'm going to say tv flag at least six characters is actually false. So that rules, that rule is not passing. [\[23:32\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1412s) All the other ones are. And the next thing I'm going to do, I'm going to say bull is valid equals TV is valid. Some meaningless text as password. Now, this is actually meaningless text as password because [\[24:03\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1443s) I'm not actually testing that it's using the string here. I'm testing that it's calling the underlying rules. The string right now is meaningless. me some meaningless and I'm asserting that something is false and that would be the is valid method. So I'm pretty sure that when you're looking at test right now this seems very very weird to you because there is nothing here that makes much sense but this is the way we are testing the the logic. [\[24:39\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1479s) This is the way we generate in test driven manner. A testable validator is a validator that allows us to muck around with the behavior. And what are we doing with the behavior? We're saying, well, all rules are going to pass internally besides this rule. Now, when that's true, when all this is true, but this is false, the is valid should actually return false. So, let's make this happen. Let's generate the testable validator class [\[25:11\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1511s) And that's actually going to inherit from a validator class which is not existing right now. So let's create a class and this class is going to be our production code. So this is our test specific subclass and this is the class that we're actually testing. Now let's turn our attention to this interesting method which right now does not do anything. [\[25:48\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1548s) So let's create a field called flag list characters. And now this method will actually set all the flags. Right now we only have one flag at least six characters is actually actually true. Whenever we add more fields like this, we're going to add a a row here that sets that flag to true. And you can definitely write a simple reflection related method that [\[26:22\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1582s) That loops through all the fields and whatever starts with flag it sets to true. Now the only thing left is to actually implement the is valid method and the is valid method is actually going to be generated on the testable validator class. We are going to move it quickly into [\[26:55\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1615s) A see I'm going to refactor it quickly and say that we're going to move it up into the base class. So this is valid here. So now is valid is part of the validator class and obviously throws an exception. Now where does this flag take place? [\[27:25\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1645s) Well to do that we need to implement the business rule here. So I know I'm going to do a test driven. And the way I'm going to do it is going to say override and I'm going to override a method that doesn't exist yet. And that method is going to be has at least six characters that takes a password string [\[28:09\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1689s) Now the interesting thing is that I'm going to create the method in the base class and it's going to be generated as a private virtual method. [\[28:41\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1721s) Now what we're going to do is actually say return flag six characters. So what do we have so far? We generated a production class that has an is value method and has an at least six characters method and they both throw an exception. Now we're going to write a test for this one separately. Right now we're testing this method and our test is going to prove that this method is not calling this one. [\[29:13\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1753s) How do we know? Because we are actually testing this class which inherits from this one. And in this class we override the has at least characters method and say that this one returns false. And if this one returns false, then in the production code, this one should not throw an exception. It should just return false. I hope that makes sense. Let's run the test and see what happens. [\[29:48\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1788s) And obviously I get an exception. The method operation is not implemented. So let's make the code pass as as simply as possible. And to do that, let's just say return false. Now, if I run all the test, obviously it will pass, which is weird. So, let's do another test. I'm going to duplicate this code and say, well, is valid when rule is actually true? [\[30:27\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1827s) So this one is actually true and obviously my test will fail. Expected true but was false. I can see here this is why it failed. So let's make the code actually use the production method here. [\[30:58\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1858s) So return has at least six characters. No. Why does that matter? Well, this is a problem. We're going need to prove that I'm actually going to have to send in the actual password. But as you can see, the two tests are now passing. So let's add another rule. Things should get pretty simple from here. The first rule I'm going to add is say [\[31:36\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1896s) Test is valid has no spaces is false. It's false. self testable. You know what? Let's just make this into a [setup method](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162 "Avoid setup methods (The Art of Unit Testing, 3rd ed., ch. 8)"). [\[32:14\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1934s) We'ReSharper, refactor, and public setup [\[32:50\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=1970s) I just say this here TV and now let's use this TV set all rules to pass. Now TV flag has [\[33:20\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2000s) No spaces equals false, right? And TV is valid. Null doesn't really matter. on valid so when flag has no space is false the TV should testable [\[33:50\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2030s) U validator should turn false so let's generate this field and flag has no spaces is also true here and I'm going to override another method Override bull has no spaces return flag has no spaces. Let's generate this method. Create method and base class. [\[34:23\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2063s) Let's run all the tests. Bam. Expected false but was true. Interesting. So what does that mean? means that all we have to do is add this call here and If you run the test right now, they should all pass. [\[34:57\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2097s) So what happens if we want to test a rule that says one is true and the other is false? Well, we obviously don't need to test the other rule, the says when this is true because we already have something that says test when everything is true and everything passes. So now what we want to do let's say that we need to add another rule and this one is going to be [\[35:30\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2130s) As valid when rule let's say has the letter A is false has no spaces is [\[36:01\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2161s) False then it should return true. Why? I don't know why. That's just that's that's just a rule that I just made up. So it if it doesn't have the letter A, but it also doesn't have any spaces, it's okay. So let's see. [\[36:32\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2192s) This one is good. Then flag has the letter A is false. Then valid should be true. Let's create a field here. and flag has letter A is true here. Now let's override something else [\[37:22\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2242s) A. Let's implement this done. Notice nothing here happens. Now I need to add this test here. I'm running the tests. Obviously this test fails. So now I need to add my new logic here. So the logic that I need to add should be here. [\[38:25\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2305s) So if it has a space but it it h it doesn't have the letter A, it should return true. Returning true. I hope I did that right because now it's starting to confuse. Let's see by running the tests. Bam. And they all pass which is interesting. So now even if I change this to from true to false all my tests should pass even though the logic is horribly flawed. [\[38:57\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2337s) I mean it's not flawed. I mean the implementation is not there. Now I can actually let another team write the implementation here. For example some special algorithms team. So let's try to write a test for the method here. have at least six characters. And how do I do that? Well, how do I get access to this? Well, I can actually inherit in my class from testable validator. [\[39:30\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2370s) Another thing that I can do is I can actually use the attribute of friend attribute. What was the name of that? [InternalsVisibleTo attribute](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6 "Overcoming the encapsulation problem (The Art of Unit Testing, 2nd ed., ch. 3)"). So I can actually say InternalsVisibleTo attribute as a type of assembly attribute here and just put in the name of an assembly. And if that assembly is a test assembly, [\[40:04\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2404s) It can still look at the protect members or the internal members, I'm sorry. Now, the last thing that I want to do, I'm actually going to move the validator to another file I can actually start testing stuff here. So let's add a test. Now notice the name the difference in the name. The the difference is has no spaces. [\[40:37\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2437s) That's the method I'm testing. That's the difference. Has a space returns false. So string password equals space. Okay? Because that's the [simplest thing](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") I can think of. Validator V equals new validator V. [\[41:07\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2467s) This interesting, how do I get access to that? Well, I should say InternalsVisibleTo. So, I'm actually going to go to V here and say protected internal protected internal and I'm going to say V and you can see I can see here now here [\[41:39\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2499s) Now if this was a different assembly all I had to do is to put that InternalsVisibleTo and put the name of my test assembly in there and I would get the same list as it looks has no spaces let's give it the password let's get the is false has no spaces. Should I run my test? [\[42:26\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2546s) Sorry. And of course, this is nothing. Let's run my test again. And of course, my test has failed. And it's failed because has no spaces throws an exception. So all I have to do is say return password contains space. Obviously this could have been much more interesting if the algorithm was more interesting. [\[43:01\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2581s) And all tests pass. So that way I'm testing the actual algorithms and the logic that uses them separately. Now, by now you should probably be aware that there is it can get more complicated than that. But these are the basic steps that you can do to get this thing rolling. So, thank you for your time. I hope you stop by and check out my book. [\[43:34\]](https://www.youtube.com/watch?v=fKuiDFP9U0g&t=2614s) Thank you very much. ## Related - [Test Driven Validation Logic with Extract & Override](https://osherove.com/blog/2012/5/16/test-driven-validation-logic-with-extract-override.html) · osherove.com Roy test-drives validation logic with extract and override, the same technique used here on the password validator. - [TDD Kata 3 - Refactoring](https://osherove.com/tdd-kata-3) · osherove.com A password-verification kata with separate and combined rules, good practice for this lesson's approach. - [TDD Pattern: Composite Logic Development and Testing](https://osherove.com/blog/2007/9/18/tdd-pattern-composite-logic-development-and-testing.html) · osherove.com Roy's post on testing a Validate method built from smaller rule methods, the composite logic pattern in this lesson. - [Stubbing out time with parameter injection](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_64) · The Art of Unit Testing, 3rd ed., ch. 3 The 3rd edition's section on stubbing out time, an alternative to overriding the current time in a subclass. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Partial mocks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95), ch. 4 - [Avoid testing private or protected methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_160), ch. 8 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [The Art of Unit Testing, Third Edition](https://www.manning.com/books/the-art-of-unit-testing-third-edition) - [Read Michael Feathers’ book on legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226), ch. 12 - [An object-oriented partial mock example](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4), ch. 4 - [Avoid setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162), ch. 8 #### The Art of Unit Testing, 2nd ed. - [Cross-cutting concerns injection](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec5), ch. 7 - [Overcoming the encapsulation problem](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6), ch. 3 - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 #### osherove.com - [NDC Video – Michael Feathers – Working Effectively with Legacy Code](https://osherove.com/blog/2009/8/18/ndc-video-michael-feathers-working-effectively-with-legacy-c.html) - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) #### artofunittesting.com - [The Art of Unit Testing](https://www.artofunittesting.com/) [Previous lesson Code Excavations and Domain Specific Test Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/code-excavations-and-domain-specific-test-frameworks/) [Next lesson Mocking On The Edge](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/mocking-on-the-edge/) --- title: "Mocking On The Edge" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/mocking-on-the-edge.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/mocking-on-the-edge/" tags: [] author: "Roy Osherove" description: "Lesson 14 of 14 in The Art of Unit Testing & TDD Master Class in .NET (Bonus tracks on advanced patterns), 49:54. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Mocking On The Edge 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing & TDD Master Class in .NET](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) 3. Bonus tracks on advanced patterns Lesson 14 of 14 Duration: 49:54 [Watch on YouTube](https://www.youtube.com/watch?v=kUigkI9PM1o) How far can you take a tool like typemock [Isolator](https://osherove.com/blog/2006/9/27/using-typemock-vs-design-for-testability.html "Using TypeMock vs. Design for testability (osherove.com)")? What wouldyou do with it? Roy shows very advaced uses of Isolator and any [profiler based framework](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)"). ## In this lesson In a 400 level talk, Roy Osherove builds a domain specific [isolation framework](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99 "Defining isolation frameworks (The Art of Unit Testing, 3rd ed., ch. 5)") that [stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") out a third-party system by default, using the [Typemock](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html "Minimizing unit Test Fragility – 8 features in Typemock Isolator to help (osherove.com)") Open AOP API, which hooks into the CLR profiler API. For SharePoint he [fakes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") an SPSite title in one test, writes an interceptor that logs every method call, and uses [CThru aspects](https://osherove.com/blog/2009/2/25/adding-method-missing-support-to-vbnet-using-ctru-and-typemo.html "Adding Method-Missing support to VB.NET using CTru and Typemock Open-AOP (osherove.com)") in a custom test attribute to disable the SPSite constructor and skip SP global methods. He shows [SilverUnit](https://osherove.com/blog/2009/2/25/introducing-silverunit.html "Introducing SilverUnit (osherove.com)") using the same approach for Silverlight, unlike Microsoft's browser-based test framework, and ends with a song. ## Transcript 7,362 words [\[00:16\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=16s) Okay, this is a 400 level talk and there are several assumptions which I'm going to open with but that first that you you've had experience with [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)"). This is not a talk about regular unit testing. This is about creating something else. How to intercept existence existing systems and create let's say a domain specific [isolation framework](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec1 "Why use isolation frameworks? (The Art of Unit Testing, 2nd ed., ch. 5)") for a system. So for example like an isolation system for Silverlight, an isolation system for SharePoint and so on. [\[00:52\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=52s) And what I'm going to show here is step by step how I build a very simple system like that using Typemock open AOP which is an API that's exposed in the latest versions of the Typemock Isolator. I'm going to dig deep into code. So a lot of things like using Reflector delegates and lambdas and all that stuff I assume that you know. Let's see. [\[01:23\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=83s) Just so you know the tool that I'm going to be using is called Typemock Isolator. It started out as an isolation framework and one of the things that I've designed into it is that the the a thing called open AOP APIs and for to understand what happens is that Typemock does not work just like any other framework. It actually hooks up to what's called a profiler API. All the CLR calls, all the calls running innet are created in IL compiled at runtime and executed. [\[01:59\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=119s) But there are special set of APIs called profiler APIs which are just like sensors. You can connect them from unmanaged code and those sensors will let you do whatever you want and give you all the events in the system including the CLR before it compiles code during the compilation when it loads modules anything that you want. So you're basically it's like a rootkit if you think about it. It actually wraps the CLR and you can do whatever you want during the runtime of another application. If you've ever used profiling applications like trace and so on, they use those same APIs to give you all that information. [\[02:34\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=154s) Isolator takes that approach and uses it to intercept those calls and return custom values and throw exceptions and change behavior. Those are the same APIs just used very differently. So what I'm going to show is how we've actually provided a managed hook into that API and how you can intercept calls throughout the system so that you would have what I call default [stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1 "Introducing stubs (The Art of Unit Testing, 2nd ed., ch. 3)") or default behavior from a system that by default works like in production. [\[03:05\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=185s) Okay you can definitely go to my course about in August if you if you're interested just go to this URL. I think there's still like a one room left. Let's see. The next talk by the way is going to be about Silverlight unit testing and [SilverUnit](https://osherove.com/videos/2009/8/25/unit-testing-in-silverlight-silverunit-and-ms-sliverlight-te.html "Unit Testing in Silverlight - SilverUnit and MS Sliverlight Test Framework (osherove.com)") which is a unit test framework for Silverlight which I developed on top of the [CThru](https://osherove.com/blog/2009/2/25/adding-method-missing-support-to-vbnet-using-ctru-and-typemo.html "Adding Method-Missing support to VB.NET using CTru and Typemock Open-AOP (osherove.com)") engine which are you're going to see today. It's developed on top of those same APIs. [\[03:36\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=216s) And what that framework allows you to do is to run Silverlight unit tests without needing a browser running only in memory using any framework whatsoever. It intercepts all the Silverlight related calls by default. You don't have to create [mocks or stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_79 "The importance of differentiating between mocks and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") and all that stuff. You just use it like you use regular code. For anyone who's ever done here any Silverlight, you know that's basically impossible to do. [\[04:07\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=247s) I've already talked about mocks and stubs. But I want to to imagine that you have this case where you have storage managers and manager class and you have an email sender and a log writer and you don't care about the log writer. You don't care about the email sender but you are in a system where log writer and email sender are part of this third party API that wraps your system. That is you never care about them. Sometimes you make calls to them. So you want to check that they're being called, but you always want to stub them out. There is no way where you don't want to stub them out because if you don't stub them out, you're going to have a problem in the system. [\[04:40\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=280s) You're actually going to talk to some to something that you don't want to. Think SharePoint, think Exchange, think Active Directory. You want to separate to isolate the system to something that is more manageable under test. So what I'm proposing is that instead of what we did so far is in an ad hoc manner create mocks and stubs to simulate the email sender and the log writer and that those mocks and stubs went away after the test was finished. [\[05:12\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=312s) What if we never have to create stubs for it ever again? What if the system by default is a big stub but my code doesn't realize it? The general rule with mocks and stubs is people usually say only stub or mock what you own. Here I'm going to say let's do the opposite. Let's stub out everything we don't own. Everything that's outside our code is going to be [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)"). [\[05:46\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=346s) Here's an example. Anyone here ever develop in SharePoint, by the way? Okay. Plenty of SharePoint developers here. I want to show you an example of a SharePoint related test. And for those of you who don't know the SharePoint API, SharePoint API is actually not that bad. It has a couple of interesting objects. One of them is called SPSite. You cannot run tests against SharePoint without having SharePoint installed on your machine. However, the tests that you're about to see are written against SharePoint. [\[06:17\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=377s) I don't have SharePoint installed. All I have are a couple of SharePoint DLS. I am actually stubbing up the SharePoint DLS. First, I'm going to do it in an ad hoc manner. I'm just going to do it on the specific test and then I'm going to show how using the Typemock Open AOP APIs. Typemock open AOP API. Say that five times fast. I will stub out things by default so that everything I touch will actually be fake. Now I'm going to use Typemock Isolator because that's the only tool that can today fake out SharePoint. [\[06:54\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=414s) Let's look at just at the name of the test for a second so we see what I'm trying to test. When you're trying to get a site title, given a specific URL, bring the site title. So, what I want to do is I want to to fake a site that has a specific title and a specific URL so that when the code goes to that URL, I want to see that it brings me that title. That's a very simple thing that you can do in SharePoint. Now the way I do it with the ad hoc testing with ad hoc APIs is by creating a fake instance of SPSite. [\[07:24\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=444s) Isolate.fake.instance of SPSite. What's interesting is that SPSite by default is sealed. You cannot inherit from it. Doesn't implement any interface. And any other framework would not be able to do this. I create an a fake site and then I fake out the behavior fake site.root.title. Notice that there is an object with a property here. So there's like a chain of calls. We'll return [\[07:56\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=476s) This title just a fake title. So this is a static this is sorry this is not a static property. This is just a call chain that will return something. Now the big point here is that I don't know when the SPSite will be created in production code. So I can swap out the next instance of SPSite. So isolate.swap.next instance of this type with the fake site with all the behavior that I just told you. Now the production code might look something like this. [\[08:28\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=508s) New SPSite bring me the title and indeed this is what I will get. This is a very simple way to just isolate one specific thing in the system. Doesn't really mean anything. Now I want to try to do this on a piece of code that is one level removed. So this is I create a class called sprapper and sprapper is just think of it like a helper. I initialize it with a URL and it will have just the title already ready for me. [\[09:02\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=542s) So I give it a URL and when I say get site title, it does all the things that I did before with a site. Notice that it also calls methods that I don't care about like dispose here and dispose there. And these are the kinds of methods that I shouldn't care about in my tests. These are like methods they say forget about it. Always ignore these methods. I shouldn't be needing to fake them out for every test that I have if this is the only domain I'm testing in. [\[09:33\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=573s) Now, the same code that I did in the previous test will work even if I initialize the SP wrapper code. So, this there is no difference. I just I what I'm showing is that this will also work regardless of where the call to the new constructor will happen. If it's in my code, if it's some other code, if it's in third-party code, because we are using the profiler APIs, we get the notification that a call to constructor is called anywhere even if it's in third party code and we can in intercept that and return fake behavior. [\[10:10\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=610s) So what now what I want to do is I want to create something called an interceptor. An interceptor is just a logical thing that I just thought about. It's something that uses the Typemock API open AOP stuff to intercept calls at runtime. Just intercept. So the first thing I want to do is just intercept and see all the calls that are running in the real system. I'm not going to actually do any testing. I just want to show you what goes on when I implement these two lines. [\[10:43\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=643s) This interceptor I'm going to show the code. I just say start and stop and between them all the calls will be written to the console. Let's just see how that runs and then I'll show you how the code looks what it takes to do something like this. So just imagine that you just hooked up into the the the the APIs of the CLR and you get notification on every method that happens in the CLR from now on. These are all the methods that happen with the type names. [\[11:14\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=674s) I could also write down the parameter values and all that stuff. As you can see, there are methods from Microsoft SharePoint here, but there's also a method from testdriven because that's the runner that I use because it's managed. The CLR also notifies me about this. So, these are things I didn't even care about. I also intercept. Let's see what else there is. There are calls from [\[11:44\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=704s) Let's see is there like an NUnit kind of stuff here. Oh look at that system diagnostics.process.dispose I even cut that. So just imagine I can actually catch any call to the system as long as that method or type is not inside mscorlib.dll. It's not because I can't. because we chose not to do that because if you intercept mscorlib.dll DLL you get a very very bad runtime a slow slowdown [\[12:17\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=737s) But anything that's not mscore DL we can intercept we can change behavior that means that we can intercept SharePoint we can intercept Silverlight anything this is the this is the constructor for the SharePoint wrapper and this is what the code looks like this is the simple interceptor the simple interceptor actually uses a class called event tunnel. Event tunnel is inside you get this basically when you download the the isolator type.in internal.hooks.event [\[12:51\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=771s) Tunnel. You're not supposed to use this unless you're going to build some sort of framework. Now event tunnel has two main delegates that you can register to. These are not even events. These are delegates because we want you to be able to even nullify them when you want to. Now once you register to them they start working. Once you unregister from them that is you make them null they stop working. These are the two main hooks the two main sensors into the CLR. [\[13:22\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=802s) Now there are two main things you can do here. There is one event that asks you if you would like to intercept a specific method. For example, it will give you the name of the method and the type name and all that kind of stuff. You say, okay, if this is a SharePoint method, I would say yes, I want to return result that will intercept. And if I did say yes, I would also get this. I would get a special delegate that invoked that's being invoked as the method is being called. [\[13:55\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=835s) It will be called for any type of method. if it's a a static constructor, if it's a constructor and all that stuff, I will get this and it all the information I need is going to be inside the arguments parameter. For now, my implementation is very very simple. Let me just show you that implementation. okay. By default I always say args for for should intercept decision. [\[14:30\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=870s) I can only say intercept or don't intercept or let isolator decide. That's the default. Sometimes you want isolator to decide for you when you don't care. By default, you don't care about something until you say I care about this. And the reason sometimes you want to say intercept is because maybe no one told isolator to do something with this method. So you say no no no I want to force I want to I want to be able to use this method by default I intercept everything I always say intercept. [\[15:00\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=900s) Second thing I do for all method calls in the system I write to the console args.ype name and args method name but I also have the parameter values the generic parameters to the method and all that stuff so I can resolve everything essentially. These are the two hooks that isolator uses. So if you wanted to, you could actually use these two delegates to build your own Typemock Isolator with your own API with the same abilities. There is almost nothing you can do that that we do that you cannot do with this API [\[15:33\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=933s) Except no I think that actually you can do everything once we do this we let we give you all the power that you want. Now when I say stop I just nullify them. as I nullify them, it will stop throwing the events which is good for performance. Of course, for every call in the system, I want I'm going to get very poor let's just intercept the calls that are happen on [\[16:05\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=965s) SharePoint. This is how I would use it on a regular method call. And let's see this is SharePoint interceptor. Now with a SharePoint interceptor, what I did is I already changed my design. I created a class called interceptor base. It does the same thing you just saw. Registers to the two delegates, but it just has two methods that you need to implement. On method call and should intercept decision. [\[16:35\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=995s) Why did I do a base class? Because maybe later I will want to do a different class that has different logic. So this is the same event tunnel stuff with two virtual methods. By default, it always says intercept and writes to the console. If I overwrite these methods, I can do whatever I want. So I inherit from this class and I say, look, on every method call, I want you to check if it's static. How do I know if a method call is static? The args has a property called context. That's the actual target object on which the method is performed. [\[17:06\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1026s) For example, you can get the invocation of a constructor on an object before the object was initialized, but you actually get the instance of an object before a constructor. Okay? So, you get the instance of an object before the constructor happened. That means it's uninitialized, but you can still do a lot of stuff with it. For example, I can say for every object created in the system, if it inherits from a specific type, I want you to always fake a method called dispose. [\[17:36\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1056s) Okay, because I intercept things at the system level, I now have the same behavior for all object in the system across the system. All future objects will behave the same. And I won't need to create special stubs for that to happen. And I'll show exactly how that happens in a second. I can just say for now, I'm just deciding if it's static, I'm writing it to the console. And if it's not static, I'm just writing it regularly. But this time I'm only intercepting if the rx.type name starts with Microsoft.sharepoint. [\[18:08\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1088s) Only then do I intercept. Everything else will just go through. Let's see how I use this and what the output is. This is a regular SharePoint interceptor. I use the same two lines and I run this test. Now I should only be getting SharePoint related stuff. You can see there is a static call here and there is you know a lot of other thing. [\[18:39\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1119s) Okay, ZoomIt died on me again. Come on just here we go and better. So we have a static method for SharePoint diagnostics there. You can see that we've discovered some really, really weird classes here. Some static stuff that happens inside SharePoint itself. Maybe we want to stop that out. [\[19:11\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1151s) I can just go through all the call stack. And actually, when I built SilverUnit, this is exactly what I did. I tried to create an instance of the new Silverlight control. And I just wrote to the console everything. And then I saw where I got the first exception and I said, "Okay, I want to fake that exception out." So I caught a method with that name and I said ignore that method. I told isolator to ignore that method and I'll show you how to do that in a second. So these are static methods like SP utility CC tour. CCTur means it's it's a static constructor. [\[19:43\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1183s) So I can disregard static constructors. I can disregard a lot of things. SP utility context download site get TLS all these stuff. So when you are at the system level, you are essentially putting your hands in the water and you're feeling everything that's flowing down there and you're going to see a lot of stuff you've never seen before. But that's exactly what we're doing with systemwide isolation. We are faking across the system. So we need access to everything. That's why the engine that is built on top of Typemock Open AOP, which I will show soon, it's called CThru. [\[20:18\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1218s) You can see through the system, touch whatever you want. Let's see something a bit more elegant. This is a SharePoint interceptor that actually takes a URL and a fake title, but this time let's see if there's but this time it actually it inherits from something called aspect. There is this SPSite aspect class here [\[20:51\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1251s) And it has some some class called aspect. What is this? This is nothing to do with Typemock AOP. This is already a project called CThru. CThru is an open source project which you can download from CodePlex. I wrote it. It's based on the open AOP stuff and it does everything I just showed but it already does all the hard work like overriding the methods and giving you the choice of what to return and what to do in a cleaner API. So let's say that I worked through all the methods that I want and I said, "Oh, you know what? [\[21:23\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1283s) I have a specific aspect in the system." And the word aspect just means that I only care about this specific thing across the system. I have an aspect that only cares about a method called about a type called SPSite. When you inherit from aspect, you also can override the method that called should intercept. Typemock will call me and ask me, hey, do you want to intercept this? I will only return true when the type name is SPSite. [\[21:55\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1315s) Why do I do this? Because this is so complex, I will create special aspects for special parts in the system and each one of them will have their own behavior. So I will inher inherit from I will create multiple classes and each one of them will take care of maybe a single type and will let it behave the way I want and I can override a bunch of several several other methods. Just so we can see the aspect class it has multiple things that I can inherit from. [\[22:26\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1346s) I can override constructor behavior. I can override the specific method behavior. Missing method behavior is only good if you're in VB. You can actually create a missing method behavior like in Ruby using this kind of thing. Should intercept as of course you should already know this. You only tell it to intercept what you care about and you can intercept static constructors. The right method is just for logging. So I overrode constructor behavior for SPSite. [\[22:57\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1377s) I always care about just constructors. Now the cute thing is I can use the Typemock open AOP and then when I get a specific call I can tell isolator to make a specific method behave in a specific way. So whenever someone calls a constructor on SPSite for every object in the system I tell isolator isolate.nonpublic non-public when called. So I want you to take over a non-public method of the object that's being created [\[23:32\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1412s) And there is a method there called is valid web URL. How did I find this method? I opened Reflector and I looked at the code and I saw ah is valid URL returns false because I say fake. So I want it to always return true so that I can give it whatever URL I want because I'm crazy. So is valid URL will always return true. Now notice this happens in the constructor. That means that every object of type SPSite will never have an invalid URL. [\[24:05\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1445s) Will never throw that exception if there was one. And make full URL will return the URL that I tell it to. What is the URL? I actually pass it into the aspect in the constructor. So I can control the URL of any SPSite that any method inside it will return. So now I can create an SPSite that when I ask what what is your address, what is your title, I can always control that. And [\[24:35\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1475s) This is very very important. The arguments that are passed in allow me to change the behavior of the original method. And here I tell it to skip the actual method. So the actual method will never be called. So that means that the constructor will never actually be called the the the original one. Only the code that I do during the construction will happen, but all the other code inside the constructor will never execute. [\[25:08\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1508s) So this way I just took a constructor of something that maybe has a lot of dependencies inside it and I shut it up. I said I don't care about this constructor. Shut it down. So every SPSite in the system will now have a constructor that's disabled. It will not call anything else. I created also another aspect of another class that I found called SP global. So I only care about type name that ends with SP global. And [\[25:39\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1539s) Here's an interesting way to say something. All the methods in SP global will all be skipped. That's it. Imagine a system where you can say, you know what, I want to skip all the methods where you have more than one parameter. So you have this flexibility here. There is an SP global which I don't care about. I want calls internal calls to SP global which always throw exceptions because maybe it's starting a couple of threads underneath or whatever to always be shut down. [\[26:10\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1570s) So that means always keep the actual method if the type name is SP global. So any call to SP global will not do anything. SP web this should be known to if you're doing SharePoint. Only intercept SP web stuff. And here what I'm going to do is to say when someone says get title I want you to return whatever title I give you in the constructor for the aspect. So now I can control the title for everything. [\[26:40\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1600s) Now to initialize to use CThru I just added a reference. I created classes that inherit from aspect. And now I need to start the engine. I need to start this somehow. To do that there is a special class in the CThru project in the DL called CThru engine. I can add multiple aspects. I can even say add all the aspects in this assembly and I say add aspect SPSite with this URL. Add the aspects for SP web and add the SP global one. [\[27:11\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1631s) So I took care of three things and I want you to start listening. And when I when they say stop, I just say stop listening and reset. And all this happens in a class called SharePoint interceptor. This is how it's used. I create a new SharePoint interceptor with this URL and this title. It will already initialize the aspect underneath with all the behavior that I said. And now I will actually be able to run the code and nothing will happen [\[27:47\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1667s) Between the start and stop. These are the same two lines. And notice that also assert here has the fake title. So these are the same lines, but the constructors are disabled. The title always returns the same thing. Nothing really happened. I disabled a whole part of the system. It's like taking someone and cutting off one of their doing a labbotomy or something. But you only care about the public API of that system. Remember this is a third-party system. So you want to disable it. [\[28:18\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1698s) The same thing was done with Silverlight. I disabled all the parts. It actually talk to the browser. If this is a method that belongs to a type that initializes stuff with JavaScript or reads XAML, disable it. Run everything just in memory. And then I had to recreate some of the behavior in memory. I'll show silver units near the end. Now, here's what I want to achieve in the end. I want to have my own attribute [\[28:49\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1729s) SharePoint unit test. So, this is a SharePoint unit test where SharePoint the the SPSite with CNN.com has this fake title. So for this specific test, I will stub out the entire system, but the system will have these properties. So you'll notice this is like a custom domain language for for for SharePoint related tests. And this has the same behavior as I I I just showed. And the way you do it, let me just run this for a second. [\[29:22\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1762s) I'm going to get another output. Where is the output window? Ctrl Alt O. See, I remember starting SharePoint isolation fake title. This is the title that I just wrote. Where did this come from? This is a custom attribute that you you get a special class that you can inherit from when you install Typemock Isolator. Let me show you how this works. When you get down to it, I've refactored the whole project into this. [\[29:54\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1794s) There is a folder called aspects. There's SP global, SPSite and so on. This is the SharePoint interceptor which you've already seen the code to which initializes the CThru engine calls add aspect and so on. And this is the attribute. Now the attribute itself inherits from something called decorator attribute. This is built into isolator. It's always been there but most people didn't realize it was there. And what this allows you to do is to intercept a method before it's executed, do something before, and do something after. [\[30:30\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1830s) And then you can execute the method in between. For example, in this case, I override the method called execute. And isolator will be responsible for calling me for invoking this method, the execute method. And here I initialize the SharePoint interceptor. I say start. I call the decorated method. This is the actual test method here. And you can do this today. And I say interceptor stopped. [\[31:01\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1861s) And here is where I write to the console. Starting SharePoint isolation in Norway. So now you'll notice that the attribute has a URL and a title. It just uses them to call the interceptor itself. Let's see if I can show this. If I run this test again, [\[31:32\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1892s) We should be able to see this. So this is just a simple way of creating your own attributes. And in fact, when we talk about SilverUnit, SilverUnit has its own attribute where you say it's a SilverUnit test. This is exactly what it does. Let me see if I can show you what SilverUnit looks like as I open things up. Anyone here work with Silverlight? Okay, I'll show you what a Silverlight unit test looks like and what happens when you when you try to run real Silverlight tests. [\[32:12\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1932s) And what I what I want to show you what the framework looks like and you'll see that the framework is based on the same basic ideas of using the CThru engine and implementing aspects and all that stuff. It just takes it one place further. For those of you who've never seen this there is a Microsoft test framework for Silverlight and if you can and what you can do is you can create custom controls or things in Silverlight and then run them using [\[32:44\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1964s) Microsoft Silverlight test framework. Now the test framework is an [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)") framework. They call it a unit test framework but it's not. It's an integration test framework. It actually runs in the browser. And I want to show you first of all what my control looks like and how the tests for the control run in Microsoft and then what they look like in SilverUnit so you can see the differences. This is the control runner. I'll just going to run this for a second so you can see the control in action. Now as I run the control where is it? [\[33:17\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=1997s) Let it run for a second. As you can see that I read my blog as I run. This is two instances of my control. I'm really into changing colors and stuff like that. If I if I click changes color if I put highlights here. So this is just control with some behavior. Right? If I do like this [\[33:48\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2028s) Is better. Now, if I were to write tests against this control using Microsoft Silverlight test, and I'm not going to show too much, but this should be enough to explain to you that when I say it's not a unit test framework, it's really not a unit test framework. It's actually a test framework written in Silverlight. These are all the tests that I wrote for it with Microsoft Silverlight test. Runs in the browser. That means it runs slowly and it has a problem because sometimes the tests fail because of timing issues. [\[34:20\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2060s) If the browser loses focus, you have a problem. Of course, you can't run it inside a build server. So, I decided to build SilverUnit, which using it, you can write tests that look kind of like this. Let me show you what tests look like, by the way, with Microsoft Silverlight framework mostly. This is what they look like. You write a test method and it's asynchronous, which is a custom attribute. And then you have to do everything asynchronously. For example, you want to add your control to a test panel, you have to incue it inside a method that takes an action. [\[34:58\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2098s) And you have to incue test complete. And you have to remember to assert also using an inq call because they're all cued one after the other. They're all done asynchronously. And it sucks because the test is very very unreadable and I hated this really. It's a big problem. Not only that, it was really hard to get started with this framework. So the SilverUnit stuff looks like this. SilverUnit intercepted everything. And this is what kind of the same tests look like. [\[35:36\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2136s) This is a regular test in SilverUnit. There is this attribute Silverlight unit test and this is SilverUnit setting template child and stuff like that inside the control which is part of the SilverUnit API. It's an API specifically for Silverlight. It's not an isolation framework. It's a domain specific isolation framework if you think about it and the asserts are also through SilverUnit. But there is nothing here that suggests asynchronicity or stuff like that. In fact, this is written using nunit. [\[36:07\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2167s) I can run all the tests using testdriven. They will all run in the output window. I can run them in command line. And what it does is just allows you to test the output. Where is the output? These are the test results for the tests I just ran four. Of course, this runs in the command line. No problem. Now just as I close this out for a second, I want to show you that SilverUnit was actually written [\[36:38\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2198s) In the in the same way that I just wrote the SharePoint stuff. SilverUnit has just a bunch of aspects that listen to a bunch of types. Most of the work creating SilverUnit was about debugging and understanding which APIs I want to take over. That's all. And about quarter of the work was about simulating various API events like how do you simulate a mouse click? How do you allow creating a control outside the browser? [\[37:12\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2232s) Because a control by default loads XAML. By default, it loads threads and all that kind of stuff. So I need to understand how Silverlight works underneath. This is SilverUnit. It's actually written in VB.NET because I'm a VB developer at heart. I wrote it in VB.NET, but parts of it are written in C# just so other people won't feel, you know, neglected. It has a bunch of aspects. In fact, these are all the aspects. [\[37:43\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2263s) They all inherit from an aspect in CThru engine. Just like you saw before, but they implement themselves on different types. For example, there is anything that inherits from control. There is an aspect anything that inherits from something called dependency object and so on. There is a dispatcher timer aspect. This is interesting because dispatcher timer is something that happens inside Silverlight controls. It's a real timer like thread related timer that I took over and I replace it with calls to a synchronous timer of my own. [\[38:15\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2295s) So it runs without the need for the CLR Silverlight runtime. There are aspects where I don't care about them. I just implement always skip the method. Very very simple. Here's for example what a control aspect looks like. What else was it? If a control act aspect is always return true if the type name contains control and the method name is is enabled for example. [\[38:46\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2326s) So I only intercept stuff if someone checks if a control is enabled in SilverUnit all controls are enabled by default. So I return I actually intercept that and I say return value or exception is true. The method behavior is return custom value and the return value is true. So controls are always enabled in SilverUnit. If you check control is enabled. By default it's enabled. [\[39:17\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2357s) Why did I have to do that? because by default controls are disabled and you had a lot of framework stuff that was trying to check that enabled was true because that meant that the browser had loaded correctly. So I just implemented functionality where the browser always loads correctly. Dependency object is something that's interesting. I only intercept constructors or static constructors and for methods that start with add. And I'll this is just an example that I showed in a different has nothing to do with anything here. [\[39:52\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2392s) Static constructor behavior is if this is a the static constructor for dependency object always skip. So no static constructors for the dependency object will ever be executed. It's a very simple concept. The constructor behavior is quite interesting. What I did here is I did look if you are getting the target type of the instance and you're checking that it equals a specific something I want you to skip the actual method but if it inherits from dependency object and it implements dispatcher I want you to implement it differently. [\[40:32\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2432s) There are special behaviors based on the type. But I can say what what this means is that with this framework, I can say everything that implements this interface in the system will always have a property that returns this property that returns true. So I can check the subclass of something. The logic is very very simple because you have the type object of something. You have the parameter values. All you have to do is to say what the logic is and what value to return. or maybe you just want to throw an exception or whatever it is that you want. [\[41:05\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2465s) So you have all the options of creating your own domain specific isolation framework. You just need to decide what APIs you want to intersect and all these APIs will be intercepted by default. There is no need from whoever is using your framework to to require something unless you specifically tell them to. That's basically SilverUnit. There isn't a lot of other things that you can do but I think that's quite enough. [\[41:36\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2496s) There is I think we are going into this direction as stuff like SilverUnit and WPF and SharePoint and Active Directory are being you know we we're programming against these things and here we have this paradigm of unit testing and all that stuff but when we program against all these third party APIs we have only two options right now we either not unit test all the code that uses them or we abstract all those other systems away using a lot of other code. [\[42:08\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2528s) This is a third way to solve the problem where instead of abstracting away, you actually create what what I call default stub or systemwide isolation so that you don't have to abstract the system. You use it as if it's the real system, but you don't care that it's actually just a stub. And I think I hope that people will build stuff on top of this that will allow us to check stuff like FxCop rules Active Directory WPF related stuff. You can actually take the SilverUnit stuff and adapt it to WPF very very easily. [\[42:42\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2562s) A lot of the APIs are very much the same. I think it would be a very very simple thing to do. You know SharePoint of course is another thing. Everything that wraps our code in a different framework. Windows workflow. Can you think of Windows workflow activities in the workflow engine stubbed out by default? No need to create your own. No need to create anything else. Can you think of WCF that doesn't do anything? Anything in the system that you want to control, but you don't want to have to do it over and over again. [\[43:13\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2593s) It's just there and doesn't do anything by default. That's what this type of system allows. Are there any questions? Okay. Who got everything I just said? Okay. Does anyone here use use WPF by the way by raise of hand or is just starting to look into WPF? Okay. You will see to WPF has the same set of issues that SilverUnit has and I hope that you start looking into that kind of thing. [\[43:47\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2627s) We already have a couple of people that are starting to use SilverUnit in their own application. because they found the Microsoft test framework that it can't run in a build server that's really missing. Let's see. Okay, for further resources, you're welcome to go and download Typemock, download the a trial version and so on. Everything is built in. If you're building an open-source kind of thing, Typemock is free. It's free for open source projects. It's only not free if you're building a commercial thing on it. [\[44:19\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2659s) The SilverUnit and CThru all the code can be downloaded for free. It's open source and it's based on Typemock which is not but just like you know Visual Studio plugins which are open source but Visual Studio is not open source. CThru.codeplex.com I'd love to hear what people would actually be doing with something like this. I think there are a lot of possibilities. Are there any questions before we move on to something else? Okay, I'll take that as an amazing no. [\[44:52\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2692s) Huh? Okay. Would like to hear a little song then? Yeah. Okay. You're just waiting for the song up until now. Wow. You know, I'm not just a a piece of meat. You can treat me like with respect like like I have a brain. No, we just want to hear you sing, dude. Okay. Can I have a volunteer? >> There you go, sir. What's your name? And >> can you give a warm welcome to Andres, please. Thank you. [\[45:23\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2723s) Do you know what you're going to get? >> You're going to get SilverUnit, a copy of SilverUnit for free. >> That's right. >> It's open source. You know that, right? Of course, you're going to get the book. Everyone gets a book today. It's my bribe to you. You know what to do. >> Okay. Can you then we won't give you the test. Can you press space once? Another time. One last time. That's it. Okay. [\[46:02\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2762s) You probably know this. I've already done this in a different framework, different piece of whatever it was talk. It's been a long day. Let me just make sure something. Thought I had a different song here. No, it's not. It's the same song. Okay. Who heard this? Ah, crap. Okay. You want to sing with me then? [\[46:36\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2796s) It's not like you don't know the words. You know what? Those who have never heard the song, the three people. This is a song that I wrote well not IRA I wrote about a team lead that I had that didn't want us to do agile development and they kept stopping us. [\[47:06\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2826s) Every build you break, refactoring you make, every mock you fake, you little snake, I'll be watching you. Every standup meeting, I believe you're cheating. Every unit test pains my chest. I'll be watching you. [\[47:43\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2863s) Oh, can't you see? This is scaring me. It would be so strange Now the clients hear everything they hear. Man, it bothers me. [\[48:19\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2899s) Oh, can't you see? Nothing comes for free. Every test you write is a waste of ice. Oh, that's hard. Every build you break, every mark you think, every test you make, I'll be watching you. Every bill you break, every mark you fake, every test you make, I'll be [\[48:54\]](https://www.youtube.com/watch?v=kUigkI9PM1o&t=2934s) Thank you very much. Okay, you are free. You have a bunch of extra five minutes, I think. Right. Thank you for pointing that out, by the way. Yeah, you're it's very well that I have a good sense of timing. ## Related - [Adding Method-Missing support to VB.NET using CTru and Typemock Open-AOP](https://osherove.com/blog/2009/2/25/adding-method-missing-support-to-vbnet-using-ctru-and-typemo.html) · osherove.com Shows another use of the CThru engine and Typemock Open-AOP, the interception tools this talk builds on. - [Digging deeper into isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6) · The Art of Unit Testing, 2nd ed., ch. 6 The 2nd edition's chapter on how unconstrained, profiler-based frameworks work, the mechanism behind this talk's tricks. - [Configuration via Typemock Interception](https://osherove.com/blog/2008/7/15/configuration-via-typemock-interception.html) · osherove.com Roy uses Typemock interception for something other than faking, the same kind of creative use this talk explores. - [Introducing SilverUnit](https://osherove.com/blog/2009/2/25/introducing-silverunit.html) · osherove.com Introduces SilverUnit, the Silverlight framework the talk shows as the same approach applied to another platform. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Defining isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99), ch. 5 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [The importance of differentiating between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_79), ch. 4 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 #### The Art of Unit Testing, 2nd ed. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Constrained and unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1), ch. 6 - [Why use isolation frameworks?](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec1), ch. 5 - [Introducing stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1), ch. 3 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 #### osherove.com - [Minimizing unit Test Fragility – 8 features in Typemock Isolator to help](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html) - [Using TypeMock vs. Design for testability](https://osherove.com/blog/2006/9/27/using-typemock-vs-design-for-testability.html) - [Unit Testing in Silverlight - SilverUnit and MS Sliverlight Test Framework](https://osherove.com/videos/2009/8/25/unit-testing-in-silverlight-silverunit-and-ms-sliverlight-te.html) [Previous lesson Testing Complex Validation Knowledge using Extract & Override](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/testing-complex-validation-knowledge-using-extract-and-override/) [Last lesson Back to the course overview](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-master-class-in-net/) --- title: "The Art of Unit Testing and TDD in Java" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/" tags: [] author: "Roy Osherove" description: "The Art of Unit Testing and TDD in Java: 21 lessons, 3 h 38 min. A free video course by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # The Art of Unit Testing and TDD in Java [Courses](https://courses.osherove.com/#courses) 21 lessons 3 h 38 min 3 sections [Start course](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-unit-testing-ideas/) [Watch on YouTube playlist](https://www.youtube.com/playlist?list=PLIBoVdbqmb0o) ![](https://courses.osherove.com/img/yt/jLDdx00oDU4.jpg) Recorded live during a three day class. ## About this course Roy Osherove teaches [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") and [test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") in Java over three days, starting with [units of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)"), [JUnit](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)") test structure and naming, and [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)") code written test-first. The second day covers [mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_79 "The importance of differentiating between mocks and stubs (The Art of Unit Testing, 3rd ed., ch. 4)"), first handwritten and then with [isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99 "Defining isolation frameworks (The Art of Unit Testing, 3rd ed., ch. 5)") such as Mockito, EasyMock and jMock. The third day covers [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)"), [faking time](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec5 "Cross-cutting concerns injection (The Art of Unit Testing, 2nd ed., ch. 7)"), the [unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") PowerMock and JMockit, and a closing talk on [build automation](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec1 "Automated builds running automated tests (The Art of Unit Testing, 2nd ed., ch. 7)") and [continuous delivery](https://pipelinedriven.org/article/continuous-delivery-values "Continuous Delivery Values (pipelinedriven.org)"). ## Related reading - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5) · The Art of Unit Testing, 2nd ed., ch. 3 From the lesson [Extract And Override Refactoring](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/extract-and-override-refactoring/): The 2nd edition's section on variations on refactoring techniques, which includes extract and override. - [Depending on a logger](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_77) · The Art of Unit Testing, 3rd ed., ch. 4 From the lesson [Introduction to Mocks and Stubs](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-mocks-and-stubs/): The 3rd edition's section on depending on a logger, the same third-party logger problem used in this lesson. - [Simulating fake values](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 5 From the lesson [Capturing Mock Arguments](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/capturing-mock-arguments/): The 2nd edition's section on simulating fake values with a framework, including checking arguments passed to fakes. - [A simple handwritten mock example](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 4 From the lesson [Demo - Mock Objects](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/demo-mock-objects/): The 2nd edition's simple handwritten mock example, like the fake logger with a written field built in the demo. - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) · osherove.com From the lesson [Simplicity is Complicated](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/simplicity-is-complicated/): Roy's post on what 'the simplest thing that could possibly work' means in TDD, this lesson's question. ## Curriculum Section 1 ### Day 1 7 lessons · 1 h 26 min The first day covers what a unit of work is and its three kinds of end results, the structure and naming of JUnit tests, keeping unit and integration tests apart, and testing exceptions. It then introduces test-driven development with string calculator demos in IntelliJ, discusses simplicity and incremental steps, answers common TDD questions and presents an experiment comparing a team that used TDD with one that did not. 1. [Introduction to Unit Testing Ideas Duration 28:25](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-unit-testing-ideas/) Roy Osherove separates good unit testing from test-driven development, which he traces to extreme programming and Kent Beck's book Test-Driven Development by Example and calls a personal practice. He defines a unit as a unit of work that starts at a public API and ends in a return value, a noticeable state change or a third-party call, the only place for mock objects. He argues for one test per end result and questions claims that unit tests make code easier to debug, maintain and understand, as when 50 tests stop compiling after a constructor change. 2. [Introduction to JUnit Duration 13:48](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-junit/) Roy Osherove contrasts manual test rigs with xUnit frameworks and introduces JUnit 4 with a test of a string calculator's add method laid out as arrange, act, assert. He explains his three-part test names (unit of work, scenario, expected behavior) and why the before, after, before class and after class attributes usually point to integration tests. He defines unit tests as running in memory under full control and keeps them in a separate package from integration tests, giving a safe green zone of tests that should always pass. 3. [Unit Testing Demo Duration 7:30](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/unit-testing-demo/) In IntelliJ, Roy Osherove shows string calculator tests that use helper methods called make calc and assert adding to avoid repetition and keep the tests maintainable. He then compares ways to test that a line throws an exception in JUnit: a try/catch block, the expected parameter of the test annotation, which he advises against because any line can throw, and an expected exception rule. With the rule, only the lines after the expect call are supposed to throw the exception. 4. [Introducing TDD Duration 12:53](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introducing-tdd/) Roy Osherove gives the three rules of test-driven development: start with a failing test, make it work in the simplest way possible, then make it better. He adds a subtract method to the string calculator test-first, choosing simple values such as one and two and deciding the order of the parameters while the code does not exist yet. He makes the test fail by returning minus one before implementing the method, and shows the IntelliJ run configuration that runs all JUnit tests in the package. 5. [Simplicity is Complicated Duration 11:37](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/simplicity-is-complicated/) Roy Osherove judges how simple a solution is by how close it is to the beginning of the method and how little it is indented. He test-drives a parse method on the string calculator, starting with an empty string that returns zero, and treats each hard-coded answer as an assumption that the next failing test, such as a single number, proves wrong. He connects these small steps to incremental development in micro iterations, with new working code that could be released every day. 6. [Common TDD Questions and Answers Duration 5:49](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/common-tdd-questions-and-answers/) Roy Osherove answers why tests are written before the code: to test the test, to think about the problem before the solution, and because there is never time to write them after the code. He says TDD makes developers try to prove that their code doesn't work, that the tests remove the fear of refactoring, and that doing the simplest thing avoids writing code nobody uses. He also explains why he has only one failing test at a time and writes the planned tests as comments. 7. [Some Numbers Duration 5:37](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/some-numbers/) Roy Osherove describes an experiment at a big company where two teams adapted the same features of a billing system, one with TDD and one without. The TDD team took 14 days instead of seven to implement the features but released in 24 days instead of 26, partly because its unit tests showed where integration bugs were not, and it had 90% fewer bugs in production. He says many companies don't try this because they fear investing without seeing the return for months. Section 2 ### Day 2 6 lessons · 54 min The second day is about testing calls to third parties with fakes, defining mocks and stubs and injecting a handwritten fake logger and fake web service into the string calculator. It then moves to isolation frameworks, comparing the strict and non-strict styles of jMock, EasyMock and Mockito, and shows how to capture call arguments with Mockito's argument captor. 8. [Introduction to Mocks and Stubs Duration 10:30](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-mocks-and-stubs/) Roy Osherove explains how to test a call to a third party with a string calculator that must send each sum to a slow logger, by adding a logger interface and a handwritten fake logger class. He defines a fake as something that looks like something else, a mock as a fake you assert against and a stub as any other fake, and allows at most one mock per test. The fake is passed in through constructor injection, and a test name such as add always calls logger shows that a mock object is involved. 9. [Demo - Mock Objects Duration 9:17](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/demo-mock-objects/) Roy Osherove writes the add always calls logger test first, as if everything already existed, with a fake logger that saves the text in a public written field and is passed to the string calculator's constructor. Because the other tests create the calculator through the make calc helper, the new constructor argument changes one place, where a fake logger is passed in as a stub. He sees only the new test fail, makes add call the logger, and has to add throws Throwable to the tests, which he dislikes. 10. [Terminology Duration 0:56](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/terminology/) Roy Osherove contrasts his simple terminology with the book xUnit Test Patterns, which gives many different names to things that look like other things. He only uses fakes: a fake that is asserted on is a mock, any other fake is a stub, and terms such as test spy can be learned later. 11. [Mocks And Stubs Duration 8:43](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/mocks-and-stubs/) Roy Osherove adds a requirement that a web service is called when the slow logger throws an exception, for example when the disk is full on a machine. The fake logger becomes a stub with a will throw method that sets the exception to simulate, and a fake web service becomes the mock object that the test asserts on. He writes the add when logger throws calls web service test with an out of memory error, and says the test name tells you what to do when the fakes get confusing. 12. [Isolation (Mocking) Frameworks Duration 19:53](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/isolation-mocking-frameworks/) Roy Osherove explains that isolation frameworks, which he prefers not to call mocking frameworks, automate handwritten fakes: they create fakes, save call arguments for verification and simulate exceptions or return values. He lists EasyMock, jMock, PowerMock, JMockit and Mockito, and uses jMock's expectations and EasyMock's record and replay to show how strict fakes, which fail on unexpected calls, break tests for the wrong reason. He recommends EasyMock's nice mocks and shows Mockito, which is non-strict by default, with verify, doThrow and parameter matchers such as any string. 13. [Capturing Mock Arguments Duration 4:36](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/capturing-mock-arguments/) Roy Osherove shows Mockito's argument captor for checking that a trace message with specific attributes was sent to the logger, by capturing the argument in a verify call and asserting on its value. He calls this clumsy and compares it with a handwritten fake class, which has to change whenever a method is added to the logger interface. A participant suggests implementing equals on the trace message, which he says can be the most readable way when the object is simple. Section 3 ### Day 3 8 lessons · 1 h 19 min The third day deals with dependencies that cannot simply be replaced, such as static methods, the current time and objects created with new, using extract and override and a time provider class. It then shows the unconstrained frameworks PowerMock and JMockit and discusses their trade-offs, and ends with a talk on build automation and continuous delivery and a short closing summary. 14. [Extract And Override Refactoring Duration 13:35](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/extract-and-override-refactoring/) Roy Osherove separates constrained isolation frameworks, which cannot override static or private methods, from unconstrained ones such as JMockit and PowerMock, which can fake them. Without them, he applies extract and override to a string calculator that calls a static logger: the call moves into a protected call logger method, which a testable subclass in the test overrides to save the text in a public field. He also explains seams, keeping logic out of the extracted method, and starting legacy code with integration tests before refactoring. 15. [Faking Time Duration 5:46](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/faking-time/) Roy Osherove explains why tests should not depend on the current date and time, and why extract and override or a time provider interface in every constructor does not suit a cross-cutting concern like time. Instead he uses a static time provider class in the production code that tests can force to a given time and reset afterwards, for example in an after method. For the machine name in the next exercise he suggests extract and override. 16. [Faking Futures Duration 2:41](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/faking-futures/) Roy Osherove discusses an exercise with a login manager that creates a new slow logger, where the test has to prove that the logger's write method is called. He compares extracting a protected method that returns the slow logger, which needs a fake subclass of it, with extracting the whole call into a protected method, which he usually prefers as simpler. 17. [Unconstrained Isolation Frameworks Duration 9:50](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/unconstrained-isolation-frameworks/) Roy Osherove shows the static logger test written with PowerMock, Mockito and JUnit, using the run with annotation with the PowerMock runner, an annotation that loads the static logger class differently, and verify static before each verified call. He then shows the same tests in JMockit, which has to be loaded before JUnit and uses non-strict expectations and verifications blocks. He does not usually recommend JMockit because calls are repeated twice and tests get wordy, and suggests starting the exercises with PowerMock. 18. [Throw Errors with Powermock Duration 1:21](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/throw-errors-with-powermock/) Roy Osherove shows how to make the write method of a static logger throw an exception with PowerMock: after mock static, doThrow with an out of memory exception is set on the static logger class, and the next call to the static logger is the one that throws. He notes that this API is not obvious at first and that a matcher such as any string tells the reader more. 19. [Discussion About Pros and Cons of Unconstrained Frameworks Duration 2:14](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/discussion-about-pros-and-cons-of-unconstrained-frameworks/) After the exercises Roy Osherove asks how unconstrained frameworks felt, concludes that they were much more complicated than refactoring, and explains that an API for faking private and static methods, constructors and other legacy code features has to be as complex as legacy code. He says tools like PowerMock and JMockit let you test code without changing it but give up the readability and maintainability that refactoring brings, so they should be used like a nuclear weapon. 20. [Continuous Delivery Duration 42:33](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/continuous-delivery/) Drawing on his book in progress Beautiful Build, Roy Osherove calls releases the best form of compilation and separates build controllers such as TeamCity or Jenkins, build agents and build scripts by what each should know. He recommends starting with a shipping skeleton, a hello world application that goes through the whole release chain, and covers cumulative builds sharing artifacts, snapshot dependencies, build script injection and parameterized FinalBuilder scripts. He also discusses the bus factor, build waves that let developers resume coding once CI passes, and why breaking the build should not be discouraged. 21. [Summary Duration 0:35](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/summary/) Roy Osherove ends the course by pointing to artofunittesting.com for more videos and free material, to his Twitter account RoyOsherove and to osherove.com for courses. He mentions that he is writing books about beautiful builds and about team leaders in software. --- title: "Introduction to Unit Testing Ideas" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-unit-testing-ideas.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-unit-testing-ideas/" tags: [] author: "Roy Osherove" description: "Lesson 1 of 21 in The Art of Unit Testing and TDD in Java (Day 1), 28:25. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Introduction to Unit Testing Ideas 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 1 Lesson 1 of 21 Duration: 28:25 [Watch on YouTube](https://www.youtube.com/watch?v=jLDdx00oDU4) We learn what does "Unit" in "[Unit Test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1 "Defining unit testing, step by step (The Art of Unit Testing, 2nd ed., ch. 1)")" mean, and what is the role of [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6 "Test-driven development (The Art of Unit Testing, 2nd ed., ch. 1)") in software development. We also learn about the three types of unit tests we can write: [Return Value Tests, State Tests and Interaction Tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec1 "Value-based vs. state-based vs. interaction testing (The Art of Unit Testing, 2nd ed., ch. 4)"). ## In this lesson Roy Osherove separates good [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") from [test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)"), which he traces to extreme programming and [Kent Beck](https://osherove.com/blog/2006/2/1/audio-interview-kent-beck-an-agile-conversation-first-iterat.html "[Audio Interview] Kent Beck - An Agile conversation (First Iteration) (osherove.com)")'s book Test-Driven Development by Example and calls a personal practice. He defines a unit as a [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") that starts at a public API and ends in a return value, a [noticeable state change](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec7 "Testing results that are system state changes instead of return values (The Art of Unit Testing, 2nd ed., ch. 2)") or a [third-party call](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)"), the only place for [mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)"). He argues for one test per [end result](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18 "Entry points and exit points (The Art of Unit Testing, 3rd ed., ch. 1)") and questions claims that unit tests make code easier to debug, maintain and understand, as when 50 tests stop compiling after a constructor change. ## Transcript 4,757 words [\[00:03\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=3s) Welcome to the [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") and [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_29 "Three core skills needed for successful TDD (The Art of Unit Testing, 3rd ed., ch. 1)") course. I want to talk about where test-driven development comes from because this course is has two parts. It has the part that teaches good unit testing practices and it has a part about test-driven development and those are two separate skills. You you can separate test-driven development from unit testing. In that you can write horrible tests in a test-driven way and you can write great tests after the code is written. So it's two separate skills of writing good tests and when to write them. [\[00:37\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=37s) So but test driven development is the idea and became really official and g was given a name when people started talking about extreme programming. Has anyone heard of this term extreme programming? It's a little less known than scrum. But it's really where a lot of people from my I'm not going to say generation because I'm not old. But from from my background learned about TDD at the first time from a book by [Kent Beck](https://osherove.com/blog/2006/2/1/audio-interview-kent-beck-an-agile-conversation-first-iterat.html "[Audio Interview] Kent Beck - An Agile conversation (First Iteration) (osherove.com)") about called test-driven development by example [\[01:12\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=72s) And the and books about extreme programming and learning about this stuff and extreme programming is a is a very powerful methodology of working as developers. It's a very technical methodology. It's about what do you do on a day-to-day basis? How do you write the tests first? How do you work with user stories? And if we compare that to something like scrum, scrum is a very open-ended methodology or a process really that leaves a lot of holes in the m in the middle where you can put anything you want. [\[01:45\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=105s) So scrum doesn't tell you to write tests. But I believe that if you want to do things like scrum and iterate very quickly and release quickly without unit tests it's almost impossible because the point of iterating quickly and getting feedback is that you're supposed to be able to do something within a week or two and it's almost impossible to do something over a week or two and release something when you don't have tests because fixing things on such a quick level is almost impossible because you don't know what you broke. [\[02:20\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=140s) So half of the time will just go to fixing things and then you you'll have a hard time working forward in your features. So extreme programming is a much better technical methodology that you can use in scrum to make scrum work for example. But if we take test-driven development as a skill or as a practice, this is something you can take away and not use within the context of extreme programming. [\[02:51\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=171s) You take you can take TDD and use it in any context in any methodology. So even if you work in a waterfall organization, test-driven development can still work because TDD or test-driven development is a practice between you and your computer. Just like debugging, it's something that you choose to do personally. So just like nobody tells you when to debug things, it should be just as equal that no one should tell you when to write a test first because it's just the way you work. [\[03:22\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=202s) There is no question of whether you or not you should do it. If you choose to do it, it's the way you work. If you debug something three times and you go slowly over each line, that's your methodology of working and making sure that your code works. and TDD should feel almost the same, a personal choice. However, if your team wants to do TDD as a team and one person chooses not to do TDD, that's also a personal choice, but it's going to hurt the team. If your team chooses to start doing TDD, that's something that you can choose to do as a team as well. [\[03:54\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=234s) And it's easier when you do it [in pairs](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html "How Do You Explain Pair Programming? (osherove.com)") because test-driven development at the beginning is very difficult because there's a lot to learn. The muscle memory that we usually do is to write the code first and then the tests. But it takes time to get used to a whole new way of working. Is it worth it? We'll talk about whether it's worth it either today or tomorrow. But we'll talk about numbers as well. And what we'll see is that it it can be worth it a lot because it can save you a lot of time [\[04:29\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=269s) Until release. But the problem is that it's hard to see the numbers at the beginning. And so a lot of organizations fail to adopt things like TDD because they feel like they're wasting time and money, but they're not getting the output that they wanted. And the output can only be measured a few months or sometimes a year into the future. That's one of the reasons that a lot of organizations still do not do this today is because they haven't given it enough time to see the benefits. On the other hand, a lot of organizations do give time, but they do TDD and unit testing badly. [\[05:03\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=303s) And so the time it takes is actually worse than we're not doing it. So test-driven development can actually hurt you sometimes. We'll talk about that. But to understand TDD, we have to understand unit testing. So I want to start by by trying to understand the idea of what is a unit in unit testing. Does anyone have any concept of what is a unit? What do you think it is? You're probably right. [\[05:34\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=334s) >> Yeah. >> Well, from what what they said in some conferences, the common misunderstanding is that your unit is your a class something that you test all the aspects of a class. >> Okay. What they then told us is that unit is more of a well a functional unit sort of a a function a I'm not going to say user story but one aspect one one task that a user is supposed to do or one one task that the program is supposed to do. So unit is a task performed by a user for example or by an API. [\[06:08\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=368s) That's that's the way I kind of think about it is that I used to feel that this is a method or a class or a bunch of methods. But today I start thinking of a unit as a [unit of work](https://www.artofunittesting.com/definition-of-a-unit-test "Definition of a Unit Test (artofunittesting.com)"). something that is a use case inside the system that has a public API as an [entry point](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") where the test would test a public API and then something would happen and then one of three things is something that we end up with. So if we think of a unit of work, it's a public entry point that does something in the system. [\[06:41\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=401s) For example, we can have return value return values. If we think about return values, that's the simplest form of a use case. You put something in, you get something out, right? You call add, you with one and two, you get back three. That's a very simple thing to test, right? You you test the the unit of work. Maybe you call the add method, but inside the add method, maybe add calls three different methods all in memory [\[07:14\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=434s) And then it produces the return value directly. And that's the easiest type of test to write. But it is a unit of work because it does everything and I don't care what it does in the middle in the middle part. I just care about the return value. That's how I know it works. I could check that it calls internal methods inside, but that would actually make my test very brittle, very unmaintainable because I don't want to document how the internal code works. [\[07:44\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=464s) I just want to document the external API and how it's supposed to be used. Now, and this is also important, the test is invoking a public API and it's asserting on a return value from the same API, from the same level of code. It does not assert on a return value lower in a lower level code. It doesn't assert on a return value from a private method. It always starts with a public method. Now, there's a reason that I like to always start with public methods. [\[08:16\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=496s) Private methods tend to change. Also, private methods don't usually produce an [end result](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18 "Entry points and exit points (The Art of Unit Testing, 3rd ed., ch. 1)"). Private methods are part of a bigger process. If you think about it, private methods cannot exist without public methods. If a private method never gets called, what's the point of the private method? There has to be something that calls a private method. And if that something is private, something else has to call that something. But eventually it has to start with something public. [\[08:47\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=527s) So there is any private method is part of a bigger use case that starts with a public method. So what we want is to find the use case that says okay there is value to a user by checking this code. There is no value by checking that a private method does something because a private method always operates in the context of something public. So I I would want to check the public thing. As an example, if I call add on a method, [\[09:21\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=561s) But I check an internal field in the class that it's set to the right value and my assert passes, right? A private field sometime maybe I'll use reflection or something and I'll check that the private field contains the right sum and my test passes. Does it mean anything? It means that the private field has that value, but it doesn't mean that the code actually works because maybe [\[09:51\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=591s) The methods that produce the result don't use that field. Maybe they use a different field by mistake. So my code might still not work even though my test passes. That's why I want to test things through the public APIs and also assert at the same level either through the same API or through a different one. So this is the simplest kind of test and it's called a return value test but it also can be thought of for exceptions because an exception is a form of return value at the same level of API. [\[10:23\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=623s) So you put something in you get something back. That should be the [simplest test](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)"). Those are not my cats. The second level of tests are when you have methods that don't return anything. So you invoke a method. Let's call the method add user. So if we save the meth the method add user doesn't return anything. So what's the point of the method? It changes the state of the system. [\[10:55\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=655s) If we add the user to the system, the system now has a different state. Now again the question is if I add the user to the system what's the best way to test that as user works is it by going let's say it's an [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)") is by going to the database sorry log in with the new user that's a much better way why why do I think that's a better way than going to the database and checking the user there any ideas [\[11:29\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=689s) >> you Yeah, it could it could be in the database and still not work. That's the point. The if the user doesn't end up being able to log in, it doesn't matter in how many tables something is in the database. The point is that there's supposed to be real value at the same level of API. So if I add the user, the login for the new user should work and then I don't care whether it's using a database or an XML file or an in-memory database. I should not care. and then I can refactor the code and my test should still pass. If I change the code and I check a database field, that's a more that's a more brittle test and it also might not prove that everything works. [\[12:08\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=728s) That's why even if I'm doing integration tests and I'm doing something with a real database, I would still use the application level APIs to check that I can get something back assuming that it's in the database instead of quering the database because the fact that something is in the database doesn't mean that that something is actually being used by the application. So it has to be not just a state change but a noticeable state change something that the end user at the same level of API will notice a change in behavior. [\[12:40\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=760s) Okay so that's the second level of test. We have return value and we have [state change](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec7 "Testing results that are system state changes instead of return values (The Art of Unit Testing, 2nd ed., ch. 2)") or noticeable state change where you might invoke an API but then assert on a different API in the system. It could be that there is a public API that changes like a field that's public. That's also an example of something that's okay to test because it's a public field. It's a noticeable public field at the same level of the API. [\[13:12\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=792s) But if it's private, then it's not noticeable. Okay, here's an example of state change. You turn off the light, you see a different system. See the difference? public state change. That's not my baby, by the way, just to make sure. So, a noticeable state change is by the user of the API at the same level and the act and the assert parts of the test should be at the same level of APIs. [\[13:44\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=824s) Now, here's something a bit more interesting. if you invoke a method called add user but the requirement now is not just that it adds a user but also that it does something else like logging okay and logging happens on a web service somewhere does that mean how do I check that because this is a [call to a third party](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)") system now so you could have methods that don't return a value and do not have noticeable state changes in the system and those are methods that forward calls to other systems [\[14:20\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=860s) And that's the third type of test third type of end result that's the most complicated one because you cannot assert on the third party system right if you let's say that you you want to have a system that sends an email to the user so you will invoke a public API that sends an email to the user and then how would you assert that the email got Would you go and and open an Exchange server somewhere and then literally go to the Exchange API? [\[14:51\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=891s) You could do that, but that's a very difficult thing to do and it's going to be very very slow. It's going to be have a lot of configuration problems. So, it's going to be very hard to assert on the third party system. So, instead what we do is we create a [mock object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4 "Interaction testing using mock objects (The Art of Unit Testing, 2nd ed., ch. 4)"). We create something that looks like the third party system and we replace it in memory so that the third party call instead of going to the third party, it actually goes to our mock object and then we assert that the mock object got called [\[15:21\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=921s) And that's the only place where mock objects make sense when we have calls to third parties. So of the three types of units of work of of end results. Okay. If we have three types, return values, state changes, and third party calls, the only place where mock objects make sense is third party calls. For the rest of the things, we don't need mock objects. We might need [stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)"). We might need to [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") some dependencies on the system, but we are not going to assert against those those dependencies. [\[15:57\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=957s) The only place where we assert on something that looks like something else is in third party calls, and that's a mock object. And we'll talk about again mock objects tomorrow. But the idea is that we might use something fake in in the other places, but we're only going to assert either on state changes or return values. So the tests are going to be much easier. We're only going to assert on the fake things in the third party calls. And that shouldn't be more than five or 10% of your code. If your code has more than five or 10% in in tests with mock objects, I'm not talking about stubs, but mock objects that you assert against, then you're probably asserting too much. [\[16:35\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=995s) You're probably oversp specifying your your tests and you're asserting on things that you shouldn't be asserting on. For example, you might have mock objects on third party calls, but also you might check state changes and also make sure that something else got called just in case. And that's an example of oversp specification. It's it should be much better to just check the state of the system because if if the end result is a state change, I don't care which other objects got called as long as the end result is a good state change. [\[17:09\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1029s) If the end result is a third party call, I would assert on that. Now, we could have a method that both returns a value, changes the state of the system, and calls a third party at the same time. Do you agree? In fact, in enterprise applications, usually most methods do at least two things. They do something either state change or value and they do some logging, for example. So, you could have a method a unit of work that has two end results at the same time. [\[17:42\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1062s) For each end result, you write a separate test. You don't write all those asserts in the same unit in the same test. Why? What's the point? >> Sorry, >> it's hard to change. >> It's hard to change the test. Not as much the the the big problem, but you're going to have a problem giving a good name for the test because you're testing multiple things. But even worse, for each one of the return value of of the end results at the bottom, we will have a a separate kind of assert. [\[18:17\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1097s) One we will assert on the return value on the middle one we'll assert that something may be changed in the behavior of the system and on the third one we'll check on a mock object. What if we combine all of them and now we have three asserts in the same test and the first one fails. What's going to happen is we're going to get an exception in our test and the other two will never execute. So we won't actually know whether the other two end results actually work. That's another good reason to separate into multiple tests because when you have multiple tests, if one of the tests failed, you can still the other two still execute and so you know the state of the system. [\[18:56\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1136s) So you're like a doctor who's looking at the system at the patient and the patient is either hiding information or not. So if the patient is only telling you a third of their symptoms, you're going to try to fix the problem in the wrong place. But if you see that this that value passed but the state failed a third party call got still passed it's much easier for you to fix. If you see that all of them fail it's much easier to know maybe where the problem is [\[19:34\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1174s) Okay. This is an example of a a third particle or a mock object in real life. You know, you know what that is, by the way? That is what people do when they want to get your card information. So, they record it when you type and they actually forward it to the real system if they want to. Then they take it and they see what people clicked on. Now, so we know what a unit is. Now, let's see about popular myths about unit testing. [\[20:11\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1211s) When people do these courses, they usually do them because they think that the following are true. It's easier to find bugs and maintain and understand your code when unit testing is happening or at least somebody told them that these are true, but they're not necessarily true. Is it easier to find bugs when you have a thousand unit tests? Not necessarily. Because the unit tests could have bugs as well, right? If your unit test has a bug, [\[20:42\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1242s) How do you know? Would you write a test for your test? But how what if maybe the test for the test has a bug, etc. So, it's a very recursive problem. So, the only way I know to make sure that the tests do not have bugs is by test-driven development. Do you have something to say? For example, in TDD, you start with a failing test. So you get to see that the test fails when it should and then you move on and you make the test pass without touching the test only touching production code and suddenly the test passes. [\[21:15\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1275s) So you know that the test fails when it should and it passes when it should. So you are essentially debugging your test when you do test-driven development. That's the only way I really know on testing the test. So if your test is is testing the wrong thing, it might pass when it should have failed at the beginning and then you know you got something wrong. Or if the test is wrong and it fails and then you fix the production code and the test still fails, you might say, "Okay, maybe there's something wrong with the test." But if I don't do these checks and my tests have bugs, it's possible that I'm not going to find the real bugs when they actually happen in my production code. [\[21:54\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1314s) And then it takes longer and it's more frustrating because if if developers trust that the production code they write actually works with and they're wrong usually. Can you imagine what they think about their tests? The tests absolutely work right because they're usually simpler. But what if they don't? That's actually going to take much longer to figure out because it's the last place you will debug to know whether the bug is there or not. [\[22:27\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1347s) So, it's not necessarily easier to find bugs unless you learn how to test your tests. It's easier to maintain your system when you have a thousand tests. What do you think? Yes. No, maybe. Perhaps. >> Depends. That's a good That's a good answer. Depends on what >> I would say. to make changes to the production code or the tests. >> It depends if you have to make changes to the production code or the tests. [\[23:00\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1380s) Can you be a little more specific? >> You have to maintain your production. I would say it's easier to maintain because it's I would assume it's >> okay. So you would assume that maintaining the production code is easier >> than maintaining the test. [\[23:31\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1411s) >> PD so it's easier to read. >> Okay. >> Most likely easier to understand. >> So I'm thinking on the other side if if something fails then you have to sort of maintain your tests that is that could not be so easy. Well, here's here's an example. What if we what if we have 50 tests for a class that we just created and in each of those tests, we create an instance of that class and then we do something with it and we assert and now we decide to add an argument to the constructor of the class. [\[24:09\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1449s) What happens to those 50 tests? First of all, they stop compiling. So now we have to go and fix 50 non-compiling tests just because we added an argument to a constructor. So that sucks. Already our productivity was actually hurt by the tests. Not only did they stop compiling after we make them compile, they might still fail, right? Because they're sending maybe default values or wrong values. So now we have to go through 50 tests and fix them maybe or some of them. [\[24:42\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1482s) So everything becomes horrible when you have a lot of tests if you don't do things in a [maintainable](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)") way. And one of the things we'll see today as well is how to make your tests a bit more maintainable so that if that situation happens we know what to do. For example, don't repeat yourself in unit tests is also a powerful rule that we can use to our advantage. So not creating classes directly in all the tests is something we'll try to do. [\[25:13\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1513s) Now the third part that people usually say about unit testing is that it's easier to understand your code when you have let's say a thousand unit tests. And when they say that they actually mean that the test should be very readable in the form of almost documentation. And you can see a lot of that in things like RSpec and other forms of tests and specification. We're going to try to write write our tests. So that that's actually true. But most people, especially when they start with unit testing, the names that they give the tests are just bad. [\[25:46\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1546s) They just say they don't they don't care about the names. When in fact, the name of the test is one of the most important things that you can actually do in your tests. Because if you give it a good name, first of all, it means you understand what is the problem you're trying to solve. And second, you're treating the reader of the tests as a first class participant in the code. And I have this simple rule that when I write my tests, I I imagine that the person who's going to read my code is a serial killer that knows where I live. [\[26:19\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1579s) I don't want to piss them off too much. So, I don't want them to start asking unnecessary questions. For example, oh, what does that mean? or what is that variable and then they have to take an axe and take it to my house and knock on my door and ask me that question. So I try to protect myself from that by making things as obvious as possible in the test so that there should be almost no question that you cannot look at the code and say oh yeah I know that what that is without even switching to different methods in the test. It should be very very readable [\[26:52\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1612s) And we'll focus on that as well in this course. So only when the first three things are true, then it is truly easier to develop your code with a thousand unit tests. But if you just take one of them and you make it false, the whole experience of developing your code with unit test becomes horrible and it's not worth it. And that's kind of the thing is we have to watch out for these things and then we actually get the benefit from unit tests. but it can easily derail into something that's very hard to maintain and very hard to read to the point where you start removing unit tests. [\[27:27\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1647s) So in the first project that failed, I gave an example of some things that did not work for me. Now about six months into that project, we actually started removing some tests because the tests were hurting us. Every time we wanted to make a change to something, some tests were failing and we didn't have time for that stuff. we we actually had more important things to do. And we knew that the tests were failing for all the wrong reasons. They weren't failing because the code wasn't working. They were failing because they expected things to work internally [\[28:01\]](https://www.youtube.com/watch?v=jLDdx00oDU4&t=1681s) And we didn't actually care about. We kept changing it. Oh, that method should have been called three times and it was called four times. Well, the end result is the same. So, what do you care? Or that method is called in once instead of three because we optimized. Everything works faster. Result is still the same. Test is is failing. That's what you want to avoid. ## Related - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19) · The Art of Unit Testing, 3rd ed., ch. 1 The 3rd edition's section on exit point types: return values, state changes and third-party calls, the lesson's three kinds of end result. - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) · osherove.com Roy's post on what 'unit' means: a unit of work from an entry point to exit points, as defined in this lesson. - [Value-based vs. state-based vs. interaction testing](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec1) · The Art of Unit Testing, 2nd ed., ch. 4 The 2nd edition's comparison of value-based, state-based and interaction testing, the three test types introduced here. - [TDD: Not a substitute for good unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_28) · The Art of Unit Testing, 3rd ed., ch. 1 Section arguing TDD is not a substitute for good unit tests, matching the lesson's separation of unit testing from TDD. - [Definition of a Unit Test](https://www.artofunittesting.com/definition-of-a-unit-test) · artofunittesting.com Roy's written definition of a unit test and unit of work, with the properties of a good unit test. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Entry points and exit points](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18), ch. 1 - [Three core skills needed for successful TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_29), ch. 1 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8), ch. 8 #### The Art of Unit Testing, 2nd ed. - [Testing results that are system state changes instead of return values](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec7), ch. 2 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1), ch. 1 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6), ch. 1 - [Interaction testing using mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4), ch. 4 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 #### osherove.com - [\[Audio Interview\] Kent Beck - An Agile conversation (First Iteration)](https://osherove.com/blog/2006/2/1/audio-interview-kent-beck-an-agile-conversation-first-iterat.html) - [How Do You Explain Pair Programming?](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html) - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) [Next lesson Introduction to JUnit](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-junit/) --- title: "Introduction to JUnit" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-junit.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-junit/" tags: [] author: "Roy Osherove" description: "Lesson 2 of 21 in The Art of Unit Testing and TDD in Java (Day 1), 13:48. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Introduction to JUnit 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 1 Lesson 2 of 21 Duration: 13:48 [Watch on YouTube](https://www.youtube.com/watch?v=n6mSLc2vrko) In this talk we start learning about [JUnit](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)") and some of its APIs. We also learn when NOT to use some of them. ## In this lesson Roy Osherove contrasts manual test rigs with [xUnit frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)") and introduces JUnit 4 with a test of a [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)")'s add method laid out as [arrange, act, assert](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "The Arrange-Act-Assert pattern (The Art of Unit Testing, 3rd ed., ch. 2)"). He explains his [three-part test names](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html "Naming standards for unit tests (osherove.com)") ([unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)"), scenario, expected behavior) and why the before, after, before class and after class attributes usually point to [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)"). He defines [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") as running in memory under full control and keeps them in a separate package from integration tests, giving a [safe green zone](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec2 "Mapping out tests based on speed and type (The Art of Unit Testing, 2nd ed., ch. 7)") of tests that should always pass. ## Transcript 2,270 words [\[00:04\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=4s) Now when I when I talk to people who don't have [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1 "Defining unit testing, step by step (The Art of Unit Testing, 2nd ed., ch. 1)") experience, I explain to them that all developers have already done unit testing because I don't know a single developer that doesn't check their code before handing it off to someone else. They do it, but they do it manually. They maybe create a form or web or or a page or something with buttons and text boxes like text one and command button one and all that stuff. And if you click them in just the right order, it will invoke your code and you'll know that the code works. [\[00:36\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=36s) So I've I've done that. Most developers have done these test rigs where they know how to run and know that the test is working. But the problem is that that's not structured. You cannot give that kind of test to everyone in your team and they will just instantly know how to run that. And the the big question is can I run my test that I just created three months from now when I forget how to use that form? Can anyone on my team run the things that I just wrote, the test rigs that I just did three months from now when I'm not here and I'm in a different department? [\[01:12\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=72s) And if the answer is no, then it's not repeatable. It's not structured. And that's one of the reasons we also do it only on parts of our code because some parts of our code are really hard to test. So we only test the things that seem easy to us or we test only the things that are the most complicated because even the easy things take a lot of time to test manually. So we only save it for the really difficult stuff. And that's where frameworks come in. [\[01:42\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=102s) Unit test frameworks. Now the the the collective name for the unit test frameworks is called [XUnit frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec1 "Frameworks for unit testing (The Art of Unit Testing, 2nd ed., ch. 2)") and the idea is that the X stands for the first letter of the language. So the first one was for Smalltalk was called SUnit. [JUnit](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)") was one of the first to to arrive as well. We're going to look at JUnit 4 and I'm assuming that you all have access to JUnit 4. [\[02:13\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=133s) And what's nice about it is once you know how to work with one XUnit framework, it's very easy to translate your knowledge into other frameworks. So if you wanted to switch to something like TestNG later, you shouldn't have any problem switching because a lot of the constructs are very much the same. But I believe that JUnit is is definitely good enough and it's supported well enough in most of the tooling that it shouldn't be a problem to use it. [\[02:48\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=168s) This is the structure of a very very simple test with JUnit. Now the structure is very simple. We have a class and the class has methods. The methods are public void. They don't take parameters. They could take parameters but we'll talk about that maybe later. I usually don't use that in Java. There is a special attribute on the method called test which is from JUnit [\[03:18\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=198s) And the test itself is just a simple method that does three things and those are called colloquially arrange act assert and I've even separated them with an empty line between each of them. Now the thing that we're testing is [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)") but the [unit of work](https://www.artofunittesting.com/definition-of-a-unit-test "Definition of a Unit Test (artofunittesting.com)") in string calculator is called add or add is the [entry point](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18 "Entry points and exit points (The Art of Unit Testing, 3rd ed., ch. 1)") that's the public entry point that starts the unit of work. The situation I'm testing is that when I'm calling it with an empty string and I'm expecting a return value that is the default value in the system. [\[03:56\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=236s) The default value happens to be zero but I'm not documenting it in the name. Now I want you to notice the name that I'm using because the [naming convention](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_168 "Naming unit tests (The Art of Unit Testing, 3rd ed., ch. 9)") is very important. You can adapt adopt your own naming convention. I find that this naming convention works for me really really well. And the naming convention main works this way. It has three parts in the name. The part is the start of the unit of work, the scenario under which you you are testing and the expected behavior or the return value for the [state change](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec7 "Testing results that are system state changes instead of return values (The Art of Unit Testing, 2nd ed., ch. 2)") or the [call to a third party](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)"). [\[04:30\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=270s) And I separated them with underscores because it makes it a bit more readable. And the underscores are especially helpful for people who are new to unit testing. When they remember there has to be three parts. And when you have a good name with all these three parts built in, it's much easier to understand what the test is supposed to do. And a lot of people who start out with unit testing, they start out with only providing two or even just one of those pieces of information. For example, they would say, "Test add." [\[05:00\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=300s) And then, of course, the serial killer comes in and says, "Okay, test add, but what are you testing?" I shall go to their house and ask them. Or they might say, "Test add empty string." Serial killer comes in, says, "Okay, you're calling add with an empty string. That's great, but what's supposed to happen?" And then they have to start reading the code. And the point of the name is that you shouldn't need to read the code of the test. So the third part is also very important. What's supposed to happen? [\[05:31\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=331s) It's also important because the name of the test is one of the only things you will ever see in the list of errors when things start failing. And that means that even if you have good comments on top or at the bottom, you're not going to see those comments. What you're going to see is the name of the test. Out of the thousands of tests, you're going to have 50 failing. And the name of the test is the first thing you're ever going to see. And if the name is good enough, you won't have to drill down. You can just go and start fixing things and that's going to save you a lot of time. [\[06:03\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=363s) It also feels to read a bit like like a specification. When I call add with an empty string, it returns the default value. I can make a sentence from that. Okay, that's how it should be. It almost reads like documentation. That's kind of the point. And then the arrange act part we have the arrange is where I arrange the objects under test. I might arrange [mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") [stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") the state in the system. I might create a string calculator that does something. [\[06:36\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=396s) The act part is the act part is me calling the unit of work the beginning and the assert part is the assert. Obviously assert equals is part of JUnit and there are a lot of other different asserts. The first part of the assert is the expected value. So I'm I'm reading that bottom sentence like this. Assert equals zero from result. Okay. Or assert that you get zero from result. [\[07:13\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=433s) And I find it once you get used to it it's very tur and very easy to read. There are longer syntaxes out there, but I find that this is perfectly okay once you get used to it. so let me show you some features of JUnit. For example, JUnit has has a couple of other attributes that we can use that I would not actually recommend using, but you should know that they exist. [\[07:51\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=471s) And those attributes are after class, before class, after, and before. And what they all have in common is that you can use them as hooks to do things before the tests run. after and before execute before each and every test. So if you have three tests in the class before will execute three times. Before class will execute only once. Even if you have a thousand tests, it will only execute once before all of them are run. [\[08:23\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=503s) And why would you use these this these these attributes? Well, you can see here that people are calling collection clear on something etc. But that's not a good reason. Usually I I would usually see people do that when they initialize database connections, when they put things in something that's either in database, when they clean up static stuff. And that's very important because you would use these attributes when you clean up shared resources. [\[08:54\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=534s) For example, you initialize database connection and the after class you kill the database or you roll it back to a known state. These only make sense when you have either [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") with static methods that you have to clear up static state or when you have [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec3 "Integration tests (The Art of Unit Testing, 2nd ed., ch. 1)") when you have to clean up shared resources file systems databases. Now when what we're talking about right now is doing unit testing not integration testing. So let me explain the difference. A unit testing is when you are able to run [\[09:28\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=568s) The unit of work in memory. No file systems hopefully changed, nothing database, nothing network related. It's all happening in memory and you have control over everything. Your code has control. So if it's using threads, your code doesn't have control over threads. That's part of the system, the OS. And so you have to start killing threads and processes sometimes. And so then now we start having to wait and fork and join things and all that stuff. That makes it much much messier. [\[09:58\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=598s) And it's my definition of an integration test. Everything that's not a unit test is an integration test. If it's not in memory, it's not fully automated, fully repeatable, if you don't have control over all the objects in your test, it's not a unit test anymore. And when I see someone uses these attributes, it usually means that they're not doing unit test 95% of the time. So it's a tell. The only other time when when you use it and everything is still in memory is when you have like singletons that you have to clear up between tests. [\[10:37\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=637s) That's the only time where you it would make sense to use them. And I would usually not use the top two before class and after class. Those are specifically for things that are really hard to create, take a long time. I don't So usually these are the most giving away features of initializing a system that's in the integration test. The bottom two could be used for initializing and resetting static objects, but most of the time they're used for cleaning up some something that's integration test related. [\[11:08\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=668s) And why do I care about the idea that in unit 10 and integration test should be we should know the difference? Because I separate them into two different packages. I put a unit test package and I create also an integration test package and I separate them. And unit tests always are in a package that's separate from integration tests. And the reason is is because I want to have what I call a [safe green zone](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec2 "Mapping out tests based on speed and type (The Art of Unit Testing, 2nd ed., ch. 7)"). A safe green zone [\[11:38\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=698s) Is the ability for me to check out the code from source control, right click and run all the the unit tests and they should all be green. Make sense? They should all be passing. There is no reason for a unit test which you have fully control over to not be green when you check in something in the code. Integration tests are a different situation. Integration tests might require configuration on the local machine. They might require that something is set up something. And so some of them might actually fail even if you check out the code and run them for the first time. [\[12:12\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=732s) And what's the problem with that? If you mix them up, if you have unit test and integration test in the same package and then you run them and three of them fail, what's the worst sentence that you can hear from someone say, "Oh, that's okay." Someone you see tests fail and someone says, "Oh, don't worry. That's okay." you're in trouble because you no longer [trust](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134 "How to know you trust a test (The Art of Unit Testing, 3rd ed., ch. 7)") your tests. If you had unit test package that you know is supposed to be green and some of them fail, you should literally be worried. [\[12:44\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=764s) There is no reason for those tests to fail and so you know you broke something. When you have integration test, you don't trust the results because it could be an integration test. Oh, maybe I'm just missing a database connection. Oh, maybe I'm just I didn't set up the Z drive, whatever. And that's kind of the thing is that when we separate them, we know that integration tests might be lying to us because they need configuration. But unit tests cannot lie because they run in memory. They should either be passing or failing. But we have control over everything. [\[13:16\]](https://www.youtube.com/watch?v=n6mSLc2vrko&t=796s) And if they didn't change from the time they passed, then we definitely have a problem in the production code. So the safe green zone gives us the ability to trust the tests again by separating it to unit test and integration test. we have more trust in the tests because you know we have a bunch of tests that's always supposed to be passing and if they don't we are actually worried we don't say ah it's okay okay ## Related - [The Arrange-Act-Assert pattern](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2) · The Art of Unit Testing, 3rd ed., ch. 2 The 3rd edition's section on the Arrange-Act-Assert pattern used to lay out the string calculator test. - [Naming unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_168) · The Art of Unit Testing, 3rd ed., ch. 9 Section on naming unit tests, covering the unit of work, scenario and expected behavior naming taught here. - [Mapping out tests based on speed and type](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec2) · The Art of Unit Testing, 2nd ed., ch. 7 The 2nd edition's section on separating tests by speed and type, the basis for the lesson's safe green zone. - [Avoid setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162) · The Art of Unit Testing, 3rd ed., ch. 8 Section on avoiding setup methods, related to the lesson's caution about before and after attributes. - [JUnit 4 feels like NUnit with attribute-like syntax](https://osherove.com/blog/2007/3/7/junit-4-feels-like-nunit-with-attribute-like-syntax.html) · osherove.com Roy's notes on JUnit 4's attribute-like annotations, the framework version introduced in this lesson. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [The xUnit frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39), ch. 2 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Entry points and exit points](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18), ch. 1 - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19), ch. 1 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [How to know you trust a test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134), ch. 7 #### The Art of Unit Testing, 2nd ed. - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1), ch. 1 - [Frameworks for unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec1), ch. 2 - [Testing results that are system state changes instead of return values](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec7), ch. 2 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec3), ch. 1 #### osherove.com - [TDD Kata 1 - String Calculator](https://osherove.com/tdd-kata-1) - [Naming standards for unit tests](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html) - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) #### artofunittesting.com - [Definition of a Unit Test](https://www.artofunittesting.com/definition-of-a-unit-test) [Previous lesson Introduction to Unit Testing Ideas](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-unit-testing-ideas/) [Next lesson Unit Testing Demo](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/unit-testing-demo/) --- title: "Unit Testing Demo" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/unit-testing-demo.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/unit-testing-demo/" tags: [] author: "Roy Osherove" description: "Lesson 3 of 21 in The Art of Unit Testing and TDD in Java (Day 1), 7:30. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Unit Testing Demo 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 1 Lesson 3 of 21 Duration: 7:30 [Watch on YouTube](https://www.youtube.com/watch?v=eEluzywvVwk) A short demo about jUnit basics. ## In this lesson In IntelliJ, Roy Osherove shows [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)") tests that use [helper methods](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6 "Building a test API for your application (The Art of Unit Testing, 2nd ed., ch. 7)") called make calc and assert adding to avoid repetition and keep the tests [maintainable](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)"). He then compares ways to test that a line throws an exception in [JUnit](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)"): a try/catch block, the expected parameter of the test annotation, which he advises against because any line can throw, and an [expected exception rule](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "Checking for expected thrown errors (The Art of Unit Testing, 3rd ed., ch. 2)"). With the rule, only the lines after the expect call are supposed to throw the exception. ## Transcript 890 words [\[00:03\]](https://www.youtube.com/watch?v=eEluzywvVwk&t=3s) Let me show you a little bit of features here. This is IntelliJ Let's see if I can just close others should be okay. [\[00:36\]](https://www.youtube.com/watch?v=eEluzywvVwk&t=36s) So what I'm showing here is a class called [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)"). So I have a package here called [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") and I have a class called string calculator. And there's a lot of logic but the logic is pretty simple. It basically parses out numbers and it checks if there are like negative numbers. It throws exception. If there's an empty input, then it returns a default value. And you'll notice that a lot of this is just calls to different smaller methods. [\[01:11\]](https://www.youtube.com/watch?v=eEluzywvVwk&t=71s) And what what happens is that usually with testdriven development, you start with something and you refactor into new methods. So what we're going to do is I just want to show you how the tests look. So I have a class called string calculator tests. I have a [helper method](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_161 "Keep tests DRY (The Art of Unit Testing, 3rd ed., ch. 8)") called make calc. And this is one of the reasons that I want to be able to have [maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec2 "Writing maintainable tests (The Art of Unit Testing, 2nd ed., ch. 8)") is is achieved. [\[01:41\]](https://www.youtube.com/watch?v=eEluzywvVwk&t=101s) One of the ways to achieve maintainability is by not creating the string calculator directly in my tests but by having it directly called by a helper method. So this is an example of creating the calculator and I actually have a method called assert adding and in assert adding what I do is I basically have this little test right here. I started with a little test and I saw hey I keep repeating myself. [\[02:14\]](https://www.youtube.com/watch?v=eEluzywvVwk&t=134s) So maybe I'll just call add here and I will just assert against it and that will help me remove some of the repeating in the code. So I came up with a helper method. This is not a test but it does have an assert inside it. Another feature that's important is when we want to test [\[02:47\]](https://www.youtube.com/watch?v=eEluzywvVwk&t=167s) A line like this. Let's say if there's a number that's negative, throw an illegal argument exception. How do I test a line that throws an exception in [JUnit](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)")? Well, there are several ways. One way is to use try catch, but there are that's usually frowned upon these days. because it makes the test very very unreadable. Basically, if I wanted to, I would write something like this. Test public [\[03:18\]](https://www.youtube.com/watch?v=eEluzywvVwk&t=198s) Void add with negative rows. I just call it zero because they have different examples of that. And then here I would say try minus one. And here I might say catch [\[03:48\]](https://www.youtube.com/watch?v=eEluzywvVwk&t=228s) I could choose the exception and throwable E. And here I might say look if you got all the way to the exception all good. Okay, I can just say return. But if you got all the way out of the exception [\[04:19\]](https://www.youtube.com/watch?v=eEluzywvVwk&t=259s) And I can say assert false true, I can make the test fail on purpose and say [expected exception](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6 "More NUnit attributes (The Art of Unit Testing, 2nd ed., ch. 2)"). And that's an example of how you would how would you would make the test fail on purpose. I usually just say this because the name of the test is good enough that I don't have to give to give a good comment. [\[04:52\]](https://www.youtube.com/watch?v=eEluzywvVwk&t=292s) So that's the like the that used to be the the good way of doing things because you wanted to say okay this line is supposed to throw an exception but then with the latest version of JUnit I could just say test and say expected equals illegal argument exception.class. Don't use this. Okay, I'm showing you so that you know not to use this. And the reason is it's basically putting the whole test in a big try catch. [\[05:24\]](https://www.youtube.com/watch?v=eEluzywvVwk&t=324s) What's the problem with that? Means that any line can throw that exception. So if the wrong line throws an exception, something in the [arrange part](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "The Arrange-Act-Assert pattern (The Art of Unit Testing, 3rd ed., ch. 2)") for example, your test will actually pass. It will lie to you. Okay. So expected exception is something that exists that you should not use. Here's a bit of a cleaner way to do it. You create something called a rule. A rule is something that you can set that applies to all the tests. For example, I set a rule and then a public field expected exception and I call it thrown. [\[05:59\]](https://www.youtube.com/watch?v=eEluzywvVwk&t=359s) And I say the expect the default of expected exception is none. This is part of the JUnit APIs. And then in my test I would say make the calculator and then I would say thrown expect illegal argument exception.class. And here I would have that line. So now only the lines that appear after this line are the ones that are supposed to throw the exception. Okay. [\[06:30\]](https://www.youtube.com/watch?v=eEluzywvVwk&t=390s) Now why is that important? because it allows me to say that this line shouldn't throw an exception. If this line throws that exception, my test will fail. But if this line throws an exception, my test will pass. So I'm able to say that specific line is the important one. And if you if you if you don't like this rule, this working with rules, you can always go back to try catch. That's the And you'll notice that even in try catch you can actually make that mistake of saying oh just make the calc. [\[07:02\]](https://www.youtube.com/watch?v=eEluzywvVwk&t=422s) So here I'm just going to extract a variable from it. And now this line is the only nine that's supposed to throw an exception. ## Related - [Checking for expected thrown errors](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2) · The Art of Unit Testing, 3rd ed., ch. 2 The 3rd edition's section on checking for expected thrown errors, the exception-testing options compared in the demo. - [Keep tests DRY](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_161) · The Art of Unit Testing, 3rd ed., ch. 8 Section on keeping tests DRY, the reason the demo uses make calc and assert adding helper methods. - [Writing maintainable tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec2) · The Art of Unit Testing, 2nd ed., ch. 8 The 2nd edition's section on writing maintainable tests, which the helper methods in the demo aim for. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8), ch. 8 - [The xUnit frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39), ch. 2 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 #### The Art of Unit Testing, 2nd ed. - [Building a test API for your application](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6), ch. 7 - [More NUnit attributes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6), ch. 2 #### osherove.com - [TDD Kata 1 - String Calculator](https://osherove.com/tdd-kata-1) [Previous lesson Introduction to JUnit](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-junit/) [Next lesson Introducing TDD](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introducing-tdd/) --- title: "Introducing TDD" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introducing-tdd.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introducing-tdd/" tags: [] author: "Roy Osherove" description: "Lesson 4 of 21 in The Art of Unit Testing and TDD in Java (Day 1), 12:53. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Introducing TDD 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 1 Lesson 4 of 21 Duration: 12:53 [Watch on YouTube](https://www.youtube.com/watch?v=g68ZONkSuZw) A short demo showing Test Driven Development ## In this lesson Roy Osherove gives the three rules of [test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)"): start with a failing test, make it work in the [simplest way possible](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)"), then make it better. He adds a subtract method to the [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)") test-first, choosing simple values such as one and two and deciding the order of the parameters while the code does not exist yet. He makes the test fail by returning minus one before implementing the method, and shows the IntelliJ run configuration that runs all [JUnit](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)") tests in the package. ## Transcript 1,743 words [\[00:02\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=2s) Let's talk about the difference between [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") and [test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6 "Test-driven development (The Art of Unit Testing, 2nd ed., ch. 1)"). If we talk about test-driven development, what we want to do is to actually say okay, I'm going to write the test before the code. And the three simple rules of test-driven development is that you start with a failing test, you make it work, and then you make it better. So you have to start with a failing test. You should not have any piece of code without a failing test. The code is read only as far as you're concerned without a failing test. [\[00:34\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=34s) If all your tests are passing, the code is read only. And then when you finally have a failing test, you have to make it work in the [simplest way possible](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)"). And what we'll see is the simplicity is not as simple as you think. Simple code is actually very hard to achieve, especially if we have been conditioned to work in a very generic way our whole coding lives. Once you make the test pass in the simplest way possible, you make the code better because you made it pass in a very simplistic way. [\[01:06\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=66s) Then you make it better, more maintainable, more readable. All these three rules together make up test-driven development. Along the way, you achieve better design, you achieve better usability of your code. And you understand the problems much better. So let's see what that would be like. Let's say that I I'm going to start with a whole new project. I'm going to say file new project create a module. I'm going to say [\[01:40\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=100s) TDD demo you know what instead of creating project let's not waste your time. I'm going to add a new feature to the [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)"). Okay. And the feature to the string calculator will be let's say that every time you call we're going to have a divide method for it. Okay. And divide will basically divide two items one upon the other. So the way to do that is not to go to the to the string calculator implementation but to start with a failing test. [\[02:16\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=136s) So, I'm going to write a test right here. public void. Now, I have to start thinking about the name. Now, the method doesn't exist yet. And that's kind of the nice thing about TDD is that the method doesn't exist yet. So, we get to name it whatever we want. [\[02:51\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=171s) Remember I want to divide something. What should we name the method? Divide. Very very in insightful. Divide. And then I have an underscore because I want to test it with some scenario. The first scenario I want to test is the simplest scenario that I can do. For example, I'm going to say divide two simple numbers. Two different very simple numbers. And what's what's supposed to happen? [\[03:28\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=208s) Divides them. Okay. I might say make calc extract variable and string calculator dot divide. Now divide doesn't exist yet. So I could so I get this nice little red sign. Now what are the two simple numbers that I can send in? Remember I want the serial killer to not come to my house. [\[03:59\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=239s) So, I want them to ask as least questions as possible. What numbers will make them ask less questions? Okay, let me let me make this even simpler. Okay, let's change it to subtract. Okay. [\[04:29\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=269s) What two numbers are the easiest to show that subtract works? So, as I'll give you a hint, it's usually the first numbers that will make you ask things less. For example, if I can give any number between zero and 100, one is better than 42. Why? Because one is the first one. It's just above the line of what makes a good number. It's just the first one. So our mind is is is usually capable of detecting patterns. [\[05:01\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=301s) If I send in one and two, it's better to sending in 45 and 76 because someone looks at 45 and 76 and says, "Yeah, but why? What's special about these numbers that you're sending in these numbers?" and also it's much more difficult to subtract in your head. Okay. So it's better to use the simplest forms and the simplest values that you can think of. So what number should we send in? What should we send in guys? [\[05:34\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=334s) >> One and one. What happens when we send in one and one? Are we going to get more questions or less questions from one and one? more. Why? >> Because the same number. >> Because they're the same number. Exactly. Looks It looks It looks special when you have two of the same thing. Okay. >> In this case, >> yes, that's true. So then how so which one would you rather have is it's not actually simple because then you don't know what the order is, [\[06:13\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=373s) >> right? It doesn't matter which order they are. >> Should it matter? >> Yes, >> of course. >> true. >> Okay. >> True. Okay. So, let's do that. Result in result equals Okay. assert equals [\[06:44\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=404s) What do we expect the result to be >> or do you want to change the order? What do you want to do? >> Well, you have to decide whe >> Exactly. So, I'm making the decision now before the code even exists. I making a design decision about the usability of the API. So I can just decide and say, you know what, it makes much more sense to me to send in subtract one from two and then assert that I get back one, [\[07:16\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=436s) Right? But if I said subtract two from one, then I might that might feel a little bit weird for me to say, oh, I would get back minus one because that doesn't feel natural for me to read. So now you get to feel like what it's like to be a user of your own API before the API exists. And if you don't like something, you can change it because the cost of changing it is zero because the code doesn't exist yet. That's kind of the nice thing about TDD is that you get to see what your API will look like before it exists. [\[07:50\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=470s) And you can get to play God and you make the API that you wish you had because we can make any decision we want. Now the code doesn't exist yet. There is no cost. So we can say subtract one from two and we can expect one for all result. Now we've made a design decision about the order of the parameters. This is important because if we would have written subtract before the test, we might not have cared about the order in terms of usability. We would have cared about the order, but we wouldn't care whether it was usable or make sense to the read user of the API. [\[08:26\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=506s) See what I mean? You we could have But we wouldn't be have it wouldn't force us to face the choice as a user which we do want. So one of the nice things about tests is that they allow you to feel like a user of your own API. So now that I have the test and notice that I'm not making a compile and then making the assert. I'm writing the whole test and I see the whole thing. And only when I'm happy with how the test is written and I like the API then I start making it compile. [\[09:00\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=540s) Now I'm going go and says I'm going to go and say create the method int subtract int how much oh there how much from return from minus how much [\[09:44\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=584s) Sorry, I can't hear you. Where is divided? >> Up there. Divides them. >> You see this is where [pair programming](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html "How Do You Explain Pair Programming? (osherove.com)") comes in. Subtract them. Now I'm going to run all the tests. And the way I did it, I just created an old test build that run all the tests in the package. [\[10:18\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=618s) Is press shift F10 here. H. And if you if you are using IntelliJ the way I did it is by editing configurations and I pressed the plus here and I created a new [JUnit](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)") one and the test kind is all in package in the whole project. That's all I did. I give it a good name. All tests dude or gal and then I just run that. [\[10:54\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=654s) Okay. Now remember that I made it compile but I didn't make it fail. So I didn't actually practice TDD now. So what I'm going to do is I'm going to say return minus one. Why minus one? Because usually when I think about something illegal or something wrong, I just return like a minus one to show that there is a real bug in the system that I would never accept. And then I just run the test again. And of course now it fails. And I can see expected one actual minus one. [\[11:29\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=689s) So for ins I usually just return minus one. So I can see the test fail and then I go and I fix it and then I should see the test passing. So now I've tested the test. Now I can go and refactor if I want to if there is something to refactor. Although I kind of like the names that I have right now. It's very very simplistic. I haven't added a lot of things yet. But the point is that I started with an API that doesn't exist yet and I made it work only after I was happy with the API that I'm designing. [\[12:05\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=725s) So during 3D dur during TDD you might change your APIs quite a bit. Okay, questions so far. And of course this is a very simplistic view of TDD. We're going to talk about [mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") and [stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") tomorrow. But this is about 95% of what you need to know. Without mock objects. It should be easy. It should be this easy because if it was very complicated to use a test framework then many people wouldn't be doing it. [\[12:35\]](https://www.youtube.com/watch?v=g68ZONkSuZw&t=755s) And kind of the point is that it should be easy to practice. But I want to talk about several questions that usually happen when I show test-driven development. And the the TDD that I showed is about the string calculator which we will do after lunch today. ## Related - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27) · The Art of Unit Testing, 3rd ed., ch. 1 The 3rd edition's section on test-driven development: failing test first, make it pass simply, then refactor. - [An updated diagram of the TDD process from the upcoming 3rd Edition of Art of Unit Testing](https://osherove.com/blog/2019/11/12/an-updated-diagram-of-the-tdd-process-from-the-upcoming-3rd-edition-of-art-of-unit-testing) · osherove.com Roy's diagram of the TDD process, a visual summary of the three rules shown in this lesson. - [TDD Kata 1 - String Calculator](https://osherove.com/tdd-kata-1) · osherove.com The String Calculator kata, the exercise the lesson extends test-first with a subtract method. - [Understanding Test Driven Development](https://www.youtube.com/watch?v=q5Xd1tmIgec) · YouTube Roy's hour-long introductory session on test-driven development, a longer walk-through of the same cycle. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [The xUnit frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39), ch. 2 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 #### The Art of Unit Testing, 2nd ed. - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6), ch. 1 #### osherove.com - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) - [How Do You Explain Pair Programming?](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html) [Previous lesson Unit Testing Demo](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/unit-testing-demo/) [Next lesson Simplicity is Complicated](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/simplicity-is-complicated/) --- title: "Simplicity is Complicated" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/simplicity-is-complicated.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/simplicity-is-complicated/" tags: [] author: "Roy Osherove" description: "Lesson 5 of 21 in The Art of Unit Testing and TDD in Java (Day 1), 11:37. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Simplicity is Complicated 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 1 Lesson 5 of 21 Duration: 11:37 [Watch on YouTube](https://www.youtube.com/watch?v=zSiFwGJ31Ew) What do I mean when I say "The [simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)")"? ## In this lesson Roy Osherove judges how simple a solution is by how close it is to the beginning of the method and how little it is indented. He test-drives a parse method on the [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)"), starting with an empty string that returns zero, and treats each hard-coded answer as an assumption that the next failing test, such as a single number, proves wrong. He connects these small steps to incremental development in micro iterations, with new working code that could be released every day. ## Transcript 1,682 words [\[00:03\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=3s) And I want to talk about simplicity. Sometimes when we solve things in the [simplest way](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)"), what we want to do is to solve it visually. We can measure how to actually measure something in terms of simplicity. And the only way I found to say whether code is simpler or not is whether the solution that I have is closer to the beginning of the method and whether it's more indented or less indented. So if it if it has more indentation like inside a loop or an if, it's more complicated than if it's not inside a loop or an if. [\[00:35\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=35s) Agreed? Also if I have to put something as a solution to make a test pass as the third line of code in a production code, that's not as simple as making it the first line of code. Maybe that makes a little less sense. So let me explain. If your code ends up here instead of here, that means that it that to actually execute your code, all the following things just above it had to execute, right? So that means that your code has to assume that something's happened before. [\[01:09\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=69s) That makes it more complicated or at least to understand the solution would be more complicated. If your code is the first line of code, if the if to make a test pass, you just add one line of code at the beginning of the method, that's the simplest thing because you don't make any assumptions about what happened before. You just do something in the simplest way possible and almost blindly. For example, clean up the inputs or things like that. And that's an example of simplicity. And we're going to find that simplicity is actually a bit difficult to achieve when we do the [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)"). [\[01:45\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=105s) Now when I do [test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") I basically practice the idea that I remove as many assumptions from my code as possible but I might write my code with as many assumptions as I can about the inputs. So I'll give you an example. Let's say that the string calculator has a method called add public void. Let's call it parse [\[02:20\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=140s) And parse can take a string with multiple numbers and those numbers can be divided with commas. Okay. And then the idea of parse is it will parse the numbers and sum them up and give you the number. Okay. So if I wanted to test parse and parse doesn't exist yet. I want to start with something then I have to start and I might start there are many ways I could start this test right but I want to start with the simplest test possible as well. So I want to start with the simplest inputs. [\[02:51\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=171s) For example I can assume that the input is an empty string in which case I would just say no numbers. let's return zero. That's better than sending in three numbers because that's something that I can incrementally work towards adding more and more features. And I can go ahead and say parse add parse an empty string returns zero or I can say returns a default. In this case I would say zero [\[03:24\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=204s) Summation. So I can say make calc extract a variable. Oh, that's not it. Extract a variable and say string calculator dot what was it? String calculator dot parse. And here I'm just going to give it an empty string. [\[04:01\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=241s) What I'm going to say now is that we basically have int result equals u parse of an empty string. And here I would say assert equals what do I expect? What is the expected value from an empty string? If you're not sure, just look at the name of the test. What is it? Thank you. Zero from result. [\[04:37\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=277s) Now if I just run this, this will of course not compile. But I can go ahead and say create the method string numbers and now I can say just return minus one because I want to see the test fail. Remember I'm just going to run the tests. Expected one that was minus one. That's what I wanted. [\[05:07\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=307s) Now I'm going to just make the test pass. So now the question is if I wanted to make the test pass in the simplest way possible, what can I send in? What should I write? Do I have to check the string? No, I can make an assumption. I can just say, hey, you know what? I'm the laziest developer in the world. I'm just going to return zero. How's that? Return zero. And I know that feels horrible. [\[05:39\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=339s) But that's kind of the point of making too many assumptions because now it feels horrible. All the tests pass and I'm back to the first rule of TDD. You want to change it. You cannot without a failing test, right? You if you think something's wrong, prove the assumption wrong. So now I get to write a new test that says you can't assume that the input is always empty. Here's an example. And I would go and I say, okay, let's do this. [\[06:16\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=376s) I'm going to write this test. Parse single number because single number is easier than multiple numbers, right? Returns that number. Here I'm going to say give me what number should I send in? One. Thank you. Not 42. That's right. And we expect Z one. And now I'm just going to run my test again. Expected one actual zero. And now I've proven that the assumption is wrong. [\[06:46\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=406s) So it's like an onion. And you start with implementing the code with as many layers of assumptions as you can. Then every new test you basically peel out one layer of the says, "Oh, that can't be true. That can't be true." So now I get to go and say, "Okay, it can't always be zero. So what's the next simplest thing that I can assume if I have to make both of the tests pass in the same time? So I might say look let's just do an if if numbers length is [\[07:19\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=439s) Zero then return zero otherwise hey let's just return one because obviously if it's not an empty string it has to be the number one right that's an assumption right there let's do that do all the tests pass damn So now we're back in the same crappy situation we were. We don't like the code, but we don't have a failing test. So we can go back and say, "No, you can't make that assumption as well, dude. [\[07:50\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=470s) So let me go back and say, actually, if you send it with a different number, so I'm just going to send in a different number." So I just have the exact same test. I'm going to send in two. I'm going to send in two. And I'm going to run the test again. Of course, that fails. Now I know I can't just return one. I can I have to do like a integer parse int [\[08:20\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=500s) Numbers. Notice that I I assume that there's only one number obviously. Now here's a question. Oh, maybe I can just get rid of all these things. Do I can I? Let's see what happens. Oops, I can't. But how long did it take me to figure that out? A few seconds. And that's kind of the another point is that when you have the tests, you can experiment and say, can I get rid of that? [\[08:57\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=537s) Can I get rid of the loop? And you have less fear in your heart when you do that. So now I know these two things have a reason to exist. And guess what? My code works incrementally. So I have two of three features working. I have zero numbers working and I have one number working and I did it within a few minutes. I can actually demo my code and instead of saying my feature either works or it doesn't, I can say that my feature partially works and I can show examples of what works and what doesn't. [\[09:29\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=569s) That's an example of incremental development. I basically did micro iterations. So with every minute or every 10 minutes I have a new feature sub feature working. That means that every day I have new functionality in the application working with tests. If every day I have new functionality I can basically take the code and release it every day if I wanted to. I don't have to wait two weeks until the feature is either finished or not. I can release every day because I always have something new passing, new working. [\[09:59\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=599s) And that's an example of how you you make short iterations work is because if you have micro iterations in your code, then a release date is just a date and iteration and end of an iteration demo is just another day because you can demo on the first day of the iteration and in the middle day and every day because you always have new features and you're working incrementally instead of taking your build a big bulk of code and making pass. [\[10:32\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=632s) Here you're making very little increments. And you also have much better feeling because you have a lot of small wins. You see green and seeing green instead of red for two weeks is a much better feeling. [\[11:04\]](https://www.youtube.com/watch?v=zSiFwGJ31Ew&t=664s) So that's the idea of making the assumptions and remove the assumptions one by one from your code. So if I have an input, it will always be empty. Nope, that's wrong. Here's a test that proves it. And it also helps if you think about it wearing two hats. One hat is the person who makes who writes the tests and the other hat is for the person who's the laziest developer in the world who has to go home in five minutes. What would they do? And then they do it in the simplest way and then the other guy says, "Oh, no, you can't do that. ## Related - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) · osherove.com Roy's post on what 'the simplest thing that could possibly work' means in TDD, this lesson's question. - [Measuring Simplicity in TDD](https://osherove.com/blog/2011/1/20/measuring-simplicity-in-tdd.html) · osherove.com Roy's post on whether there is an order of simplicity when changing code to pass a failing test. - [TDD Kata 1 - String Calculator](https://osherove.com/tdd-kata-1) · osherove.com The String Calculator kata, starting with the empty string returning zero as test-driven in this lesson. - [Comments on Corey Haines’ String Calculator TDD Kata Implementation](https://osherove.com/blog/2009/12/23/comments-on-corey-haines-string-calculator-tdd-kata-implemen.html) · osherove.com Roy's comments on a recorded String Calculator kata solution, a worked example of the same small steps. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 [Previous lesson Introducing TDD](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introducing-tdd/) [Next lesson Common TDD Questions and Answers](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/common-tdd-questions-and-answers/) --- title: "Common TDD Questions and Answers" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/common-tdd-questions-and-answers.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/common-tdd-questions-and-answers/" tags: [] author: "Roy Osherove" description: "Lesson 6 of 21 in The Art of Unit Testing and TDD in Java (Day 1), 5:49. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Common TDD Questions and Answers 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 1 Lesson 6 of 21 Duration: 5:49 [Watch on YouTube](https://www.youtube.com/watch?v=wLV5RT8cJIU) Why not write many tests at once? Why start with a failing test? why solve things in the [simplest way](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)")? These and many more questions are covered in this short talk. ## In this lesson Roy Osherove answers why tests are written before the code: [to test the test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "Testing the test (The Art of Unit Testing, 3rd ed., ch. 2)"), to think about the problem before the solution, and because there is never time to write them after the code. He says [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") makes developers try to prove that their code doesn't work, that the [tests remove the fear of refactoring](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11 "What about TDD? (The Art of Unit Testing, 3rd ed., ch. 11)"), and that [doing the simplest thing](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") avoids writing code nobody uses. He also explains why he has only one failing test at a time and writes the planned tests as comments. ## Transcript 1,030 words [\[00:06\]](https://www.youtube.com/watch?v=wLV5RT8cJIU&t=6s) Okay. Common questions about about [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6 "Test-driven development (The Art of Unit Testing, 2nd ed., ch. 1)"). Why write the test before the code? First of all, it's about testing the test. Remember so we think through the requirements and we also look at the design of requirement and that gives us a lot of a lot of problem solving abilities. Someone wrote that TDD is an excuse to think about the problem before thinking about the solution. And I think that's absolutely true. Many times we think about the solutions and we fix the wrong problem. [\[00:38\]](https://www.youtube.com/watch?v=wLV5RT8cJIU&t=38s) And a lot of times what happens when you do TDD is that you spend much more time trying to understand what it is you're doing and why you're doing it and what's the point. A lot of times you say, "Oh, I shouldn't have built that one." So it makes you talk much more with your customers. You make it fail first so you can [test the test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "Testing the test (The Art of Unit Testing, 3rd ed., ch. 2)"). And also I forgot to say that you write the test before the code because you never have time to write the test after the code. So if you write it before you always have time to do it. [\[01:11\]](https://www.youtube.com/watch?v=wLV5RT8cJIU&t=71s) We make it fails fail first because we define one problem to solve. So, I chose one problem and then I made that pass and then another problem made that pass. I don't have five different failing tests at the same time. I have one. That's kind of the point. I don't want to have a big problem solved, just a small one. And when I do solve it, I solve it as simply as possible. And that forces me to think about new tests. Because if you think about it, as developers, we're usually very not objective about our code. [\[01:44\]](https://www.youtube.com/watch?v=wLV5RT8cJIU&t=104s) We assume that it works. So when we write tests for the code after it's passing we assume we're trying to prove that the code works. And with TDD the objective is to prove that the code doesn't work. So we're thinking much more like testers. So TDD is a good way to force yourself to think about how to break your code instead of how to prove that it works. That makes the code much more resilient in terms of quality. So the simpler solutions force you to do that to say no that's assumption is wrong let's prove that that's wrong prove that that's wrong and it also usually find that your code will be much simpler than you thought it will ever be and that's a nice thing you you start with the solution in mind but you just keep doing very very small steps and suddenly everything passes and you didn't even do half of the things that you thought you will do and that's a great feeling [\[02:39\]](https://www.youtube.com/watch?v=wLV5RT8cJIU&t=159s) The refactoring part which we haven't done yet is the the part where you make the code much much easier to read. And one example is that you constantly improve the the readability and the design of the code by extracting small methods from big methods. And if we don't do it, our code is going to be very very ugly although it will pass all the tests. And one of the nice things about having those tests as a side u as a side benefit is that because you have the tests you have no fear of refactoring. [\[03:12\]](https://www.youtube.com/watch?v=wLV5RT8cJIU&t=192s) So one of the things that always happens in projects is that people are afraid to change the code. So they copy and they create a new version of the code with the changes they would like because they don't want to break the original code. And that's how code has children. Basically, the code becomes bigger and bigger and more disgusting because everything looks like a copy of everything else because everyone is afraid to change everything. And then at some point, someone says, "Ah, let's just rewrite the whole thing." And one of the nice things with this is that you're not afraid to change the code. So, it looks like like a plant that you keep growing and trimming and watering instead of replacing the plant every year. [\[03:49\]](https://www.youtube.com/watch?v=wLV5RT8cJIU&t=229s) You're just cutting the leaves where you need to. And the incremental work is very important because usually when we over plan something we don't use all the features. So imagine using something like Microsoft Word. How many of the features of Word have you actually used? Maybe 10%. Think about all the code that you've written in the hope or in the idea that someone might want to use it. How much of that actually gets used? By studies we've seen that [\[04:23\]](https://www.youtube.com/watch?v=wLV5RT8cJIU&t=263s) 60% of the code that you write usually doesn't get used. So you're writing 60% of code that you're just wasting time on average. So instead of doing that instead of planning over planning for the future we do just the [simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") and that saves us from the future risks of overarchitecture and things like that. It's also a great feeling to have this passing, this passing, this passing instead of having one big feature that works after a month. [\[04:58\]](https://www.youtube.com/watch?v=wLV5RT8cJIU&t=298s) And again, I covered the idea of why not write this multiple tests at once. I might write comments of tests that I will have because I don't want to forget, but I don't have 10 failing tests at the beginning. I have one failing and then I write another that fails. I might have 10 comments but I don't have 10 failing tests. That's important so that psychologically I am focused on a specific set of problems. For example, if you have three failing tests on [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)"), you might be tempted to fix all of them at the same time and that would make you write code much more complicated than you would. [\[05:34\]](https://www.youtube.com/watch?v=wLV5RT8cJIU&t=334s) You might end up with code much more complicated you would have if you solved it one at a time. So by separating it, you're actually making it easier for yourself to think only on very small problems and not solve too many problems that maybe you didn't even test ## Related - [Testing the test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2) · The Art of Unit Testing, 3rd ed., ch. 2 The 3rd edition's section on testing the test, the first reason given here for writing tests before the code. - [What about TDD?](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11) · The Art of Unit Testing, 3rd ed., ch. 11 The book's answer to 'What about TDD?' among its tough questions and answers, matching this Q&A lesson. - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6) · The Art of Unit Testing, 2nd ed., ch. 1 The 2nd edition's section on test-driven development, explaining why tests come first and stay small. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 #### osherove.com - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) - [TDD Kata 1 - String Calculator](https://osherove.com/tdd-kata-1) [Previous lesson Simplicity is Complicated](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/simplicity-is-complicated/) [Next lesson Some Numbers](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/some-numbers/) --- title: "Some Numbers" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/some-numbers.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/some-numbers/" tags: [] author: "Roy Osherove" description: "Lesson 7 of 21 in The Art of Unit Testing and TDD in Java (Day 1), 5:37. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Some Numbers 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 1 Lesson 7 of 21 Duration: 5:37 [Watch on YouTube](https://www.youtube.com/watch?v=-uKdh5b8J5I) [How much time to you lose](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11 "How much time will unit testing add to the current process? (The Art of Unit Testing, 3rd ed., ch. 11)") -- and save-- by using [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6 "Test-driven development (The Art of Unit Testing, 2nd ed., ch. 1)")? here are some numbers from my own experience. ## In this lesson Roy Osherove describes [an experiment](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11 "Is there proof that unit testing helps? (The Art of Unit Testing, 3rd ed., ch. 11)") at a big company where two teams adapted the same features of a billing system, one with [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") and one without. The TDD team took 14 days instead of seven to implement the features but released in 24 days instead of 26, partly because its [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") showed where integration bugs were not, and it had 90% fewer bugs in production. He says many companies don't try this because they fear investing without seeing the return for months. ## Transcript 894 words [\[00:04\]](https://www.youtube.com/watch?v=-uKdh5b8J5I&t=4s) About numbers. Here is an example of of whether it's actually worth it. And I did this study. It was [an experiment](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11#sigil_toc_id_199 "Experiments as door openers (The Art of Unit Testing, 3rd ed., ch. 11)") that I did in a big company a few good years ago. And we had two teams that were taking the same project and adapting it to different customers. So it was more like adaptation. It was a billing system. And in this case, we had two teams that were adapting pretty much the same features to do two different customers. And I was teaching there was doing consulting and the company agreed that we do an experiment and we have one team that went through the [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_29 "Three core skills needed for successful TDD (The Art of Unit Testing, 3rd ed., ch. 1)") [\[00:38\]](https://www.youtube.com/watch?v=-uKdh5b8J5I&t=38s) And we'll compare it to the results of the other team that didn't do TDD. So they did so we had the two teams and the two teams did the two features in parallel. And the team that did test driven development is on the right. And what happened is that the team that did TDD took double the amount of time, 14 days instead of seven to implement the same set of features. [\[01:09\]](https://www.youtube.com/watch?v=-uKdh5b8J5I&t=69s) But then at the end of the iteration, the team took 22 days instead of 19 to release. Not seven days more, but three days more. And obviously they that's because they had more tests, so it was easier for them to debug. They had a testing and fixing cycle. with QA it was and the testing took longer and bug fixing took longer for the other team because they did not have tests. So when they fixed bugs they also broke other code. The difference is that the other team when they broke the other code they saw it and they fixed it right there at the same time. [\[01:42\]](https://www.youtube.com/watch?v=-uKdh5b8J5I&t=102s) So it was easier for them to release the same product three days later. Now the big question is what did they get for the extra three days? So here's what they got. The amount of bugs found in production was 90% less. 90% less bugs. So the customer was happier and the developers were happy because they like the APIs. They like the fact that they have this safety net for the future for refactoring code. [\[02:12\]](https://www.youtube.com/watch?v=-uKdh5b8J5I&t=132s) So everyone was happier and that took three days more. I don't know a single manager that would not agree with that strategy. The problem is that it takes a long time to see that. In this case, it was a mini iteration, mini experiment. Now, that's not necessarily true in big organizations. So, let me be absolutely truthful. I lied. This is not exactly how it worked. This is what actually happened. Between the implementation and testing, they had integration phases. [\[02:44\]](https://www.youtube.com/watch?v=-uKdh5b8J5I&t=164s) Integration phase is when the product has to integrate with all the other modules in the company because it's a huge billing system and usually in that company integration was called hell week because everything sucked in that week. Nothing was working. Everyone was you know just working their asses off into the night debugging things. And surprisingly, the amount of bugs found was less, but but also integration took less time for the team with test-driven development. [\[03:23\]](https://www.youtube.com/watch?v=-uKdh5b8J5I&t=203s) And what we found was that when there were integration problems for the team that did TDD, the [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1 "Defining unit testing, step by step (The Art of Unit Testing, 2nd ed., ch. 1)") actually helped them to know where the the problem was not. So imagine that you have a problem integrating with something and you don't know where the bug is. So you have to start debugging all the way through the entire system stack to see whether the bug is in your logic or in integration or the configuration. But for these guys because they had some unit test for some for for the logic [\[03:57\]](https://www.youtube.com/watch?v=-uKdh5b8J5I&t=237s) And when they found a bug in integration and they saw that they had a unit test for that logic and they said oh the unit test for that is passing then the bug must be in the integration between the modules. It solved the amount of time it took them to debug where the problem was which was much faster was much much less time. So the integration phase took much less. So in reality what ended up is that they released in 24 days instead of 26 days for the other team. So that means that the team that did TDD took double the amount of time to implement because when you write tests you do write more code sometimes double [\[04:36\]](https://www.youtube.com/watch?v=-uKdh5b8J5I&t=276s) But they actually released sooner. So the investment was repaid. This was a team with about 3 months of experience. So with more experience, it would have taken them even less to write the test. So it wouldn't have been double. It would have been less. For experienced teams, it could be 50% more. But the point was that the release was actually faster. [\[05:06\]](https://www.youtube.com/watch?v=-uKdh5b8J5I&t=306s) And they still got all these things, the 90% less bugs in production. So now the big question is why isn't everyone doing this? Because not everyone can do an experiment of the 24 days. Most companies can only experiment with a few months in between at least and they're afraid of investing all that money and not seeing the ret the return. So, it's hard to see the bottom line when all you see is the top line, which is double. ## Related - [How much time will unit testing add to the current process?](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11) · The Art of Unit Testing, 3rd ed., ch. 11 The book's answer to how much time unit testing adds to the process, the trade-off the experiment measures. - [Experiments as door openers](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11#sigil_toc_id_199) · The Art of Unit Testing, 3rd ed., ch. 11 Section on experiments as door openers, like the two-team TDD experiment described in this lesson. - [How Test Driven Development proved itself in a big way!](https://osherove.com/blog/2004/9/9/how-test-driven-development-proved-itself-in-a-big-way.html) · osherove.com Roy's account of TDD proving itself on a real project, another field report like this lesson's numbers. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Three core skills needed for successful TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_29), ch. 1 #### The Art of Unit Testing, 2nd ed. - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6), ch. 1 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1), ch. 1 [Previous lesson Common TDD Questions and Answers](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/common-tdd-questions-and-answers/) [Next lesson Introduction to Mocks and Stubs](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-mocks-and-stubs/) --- title: "Introduction to Mocks and Stubs" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-mocks-and-stubs.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-mocks-and-stubs/" tags: [] author: "Roy Osherove" description: "Lesson 8 of 21 in The Art of Unit Testing and TDD in Java (Day 2), 10:30. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Introduction to Mocks and Stubs 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 2 Lesson 8 of 21 Duration: 10:30 [Watch on YouTube](https://www.youtube.com/watch?v=4fdkCJuxAfo) In this talk we learn about [mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_79 "The importance of differentiating between mocks and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") using a simple problem of notifying a logger of something that happened. ## In this lesson Roy Osherove explains how to test a [call to a third party](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)") with a [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)") that must send each sum to a slow logger, by adding [a logger interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)") and a [handwritten fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec3 "A simple handwritten mock example (The Art of Unit Testing, 2nd ed., ch. 4)") logger class. He defines a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") as something that looks like something else, a [mock](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") as a fake you assert against and a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") as any other fake, and allows [at most one mock per test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec5 "One mock per test (The Art of Unit Testing, 2nd ed., ch. 4)"). The fake is passed in through [constructor injection](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_72 "Constructor injection (The Art of Unit Testing, 3rd ed., ch. 3)"), and a [test name](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html "Naming standards for unit tests (osherove.com)") such as add always calls logger shows that a mock object is involved. ## Transcript 1,701 words [\[00:04\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=4s) Okay, so yesterday was maybe a very simplistic view of the world. Obviously, we were always able to get a return value from our methods. But today we're going to look at a very different very different scenarios. Today we're going to look at the the case of the calling a third party. We actually yesterday we did do the first the first scenario which is returning a value. [\[00:35\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=35s) We didn't actually have any tests for state-based tests yet. But we'll al hopefully have some today as well. But today we're going to focus on what happens when you call a third party. So just as a reminder, we have a [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") that starts with a public API and now the requirement will be that there is a [call to a third party](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)"), maybe a logger or something like that. And the way that we're going to to test that is [\[01:06\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=66s) We're going to have to get around the fact that we don't have control of the third party. For example, if it's a logger that's written by a different team, if it's a logger that's written by a different team, then maybe their code doesn't work yet. Maybe it has a bug. So our test will fail if we actually use their code. Maybe it works very slowly. So our test will be very slow. So we want to get get control over the third party. One way we can do it is to abstract it away and create a [mock object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4 "Interaction testing using mock objects (The Art of Unit Testing, 2nd ed., ch. 4)") something that looks exactly like the third party. [\[01:40\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=100s) But we do have control over it. And then the next leap of faith is is that we assume that if our mock object got called then the third party got called. Now it is a leap of faith because we are essentially decoupling our system from another system and we cannot really prove that the other system gets called without an [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)"). So this is the next best step which is to assume that if the mock object got called a third party system got called. [\[02:13\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=133s) And this is especially true when what we're going to do is to abstract away things either with adapters abstra interfaces and things like that. We have to assume that the system will eventually work. One way to make sure that actually happens is to have both [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") and integration tests at the same time. That means that unit tests are definitely not enough for you to know that your system is working. Unit tests are just a way for you to develop the system. [\[02:44\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=164s) They're not a way for you to make sure the system works. To make sure the system works, you have to have integration and acceptance tests. >> There is no other way because at some point things are going to try to talk to each other and that's the integration points. So here's a very simplistic scenario. If we take the [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)") that we've all just written and now we'll have a requirement that let's assume there's a class called slow logger. [\[03:15\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=195s) Now I'm calling it slow logger so that you remember not to use it in your own tests. But the requirement is that whenever you call add and you give it some numbers the sum that's returned is also sent to the logger. So we have some kind of auditing on the system. So again the requirement is that there is an arrow between string calculator and slow logger and every time you call add slow logger gets called. Now again slow logger here is a third party system. [\[03:46\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=226s) We don't have control over it. If we could make it run in memory and make it run fast, maybe we do have control over it. But the fact is this is a slow logger because it uses threads and five different web services inside. Takes 5 seconds to run. We can't use it in our actual unit test. So the be next best thing is to try to create something that looks like the slow logger. And in Java, one of the best ways to make something look like another thing is to create an interface. [\[04:18\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=258s) Makes them look the same. So we create we in we introduce a new interface into the system. We'll call it logger. And then we make slow logger implement that interface. But we need one more step. We need something that we can control. So we create a new class. I'm not using any kind of [isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99 "Defining isolation frameworks (The Art of Unit Testing, 3rd ed., ch. 5)") just yet. What I'm going to do is I'm going to create this handwritten. And this is an important skill that you need to know not to use an isolation or a mocking framework, but to do things without them. [\[04:51\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=291s) Once you do, you can understand how these other frameworks actually work. You can choose to use them or not. So, we're going to create a new class called [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") logger in our test project. And fake logger is going to implement the [logger interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)") just like slow logger. But the difference is that fake logger is our class. So we can make it do whatever we want. For example, we can add a public field to it. We can we can we can override the write method and of course not do anything so that it will run fast. [\[05:27\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=327s) So it looks like this. In my tests, the quickest way is to actually create my own little class called fake logger. Now, why am I not calling it mock logger? Any ideas? Because it might not be a mock object. So, let's talk about the the naming for a second. I call it fake logger because it looks like something else, [\[05:58\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=358s) But it might not always be a mock object. What's the difference between a fake and a mock? A fake is something that looks like something else. A mock is a fake that I assert against. Okay? So if I assert against it, it's a mock object. Okay? Otherwise, it's a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1 "Introducing stubs (The Art of Unit Testing, 2nd ed., ch. 3)"). But either way, they're both fakes. Okay? So a fake can either be a mock or a stub based on how you use it. [\[06:31\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=391s) Now, why is it important to actually distin distinct to have a distinction between them? because you should only have a single mock per test at the worst case because you only want to check one thing per test. You can have multiple stubs but only a single mock object because a mock object is an [end result](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18 "Entry points and exit points (The Art of Unit Testing, 3rd ed., ch. 1)") of the unit of work. We want to check one end result per test. If we check multiple end results and one of them fails, the others will never execute. So we won't know what's going on. So a mock object is really an assert, a hidden assert against a single end result. [\[07:08\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=428s) Anyway, I take my fake logger and I override the write method and I implement logger. And notice that I just create a public field and I set it from the variable. I make it the [simplest code](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") that I could possibly write because this doesn't exist anywhere but in the context of my unit tests. And then I'm going to write a new test right here. This is how my test would look. Notice first of all the naming add that's the entry point of the unit of work when called because I don't have a specific scenario it or I can say either always or when called. [\[07:48\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=468s) So add always calls logger or add when called calls logger. And the word calls logger the word calls is important because I'm not actually doing logging. I'm calling a third party. So the naming is important and by looking at the name I can tell that there's probably a mock object in there. The second thing that I do that I create an instance of the fake logger in my unit test and then I send that fake logger somehow into the string calculator. [\[08:21\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=501s) Now the string calculator has to have an a reference to the to the logger and one of the best ways to do it is by doing [constructor injection](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_72 "Constructor injection (The Art of Unit Testing, 3rd ed., ch. 3)") by by adding an argument to the constructor of string calculator. Now this also makes sure that this is nonoptional. So whoever is using string calculator has to send in a logger. If I wanted to make it optional I could make it a setter public setter or something. But I like to make things explicit so that I know exactly what my dependencies are. [\[08:54\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=534s) And this also helps later if I'm going to use things like Spring to to create to do [dependency injection](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_65 "Dependencies, injections, and control (The Art of Unit Testing, 3rd ed., ch. 3)") and inversion of control. Either way, I just added an argument to the string calculator and I'm going to send in the mock logger. And notice that I used a fake but I named the variable mock because in this unit test the fake logger is being used as a mock object. [\[09:25\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=565s) And then I call add and I assert against the mock object. And this is important. I can look at the I can when I review this test I can say okay so you're asserting on a mock object. If I happen to call it mock stub or sorry lo log stub or stub log, it wouldn't make sense to say assert on a stub because a stub is something that just makes happy noises when you so that you can test something else. I only want to assert against mock objects. [\[09:56\]](https://www.youtube.com/watch?v=4fdkCJuxAfo&t=596s) So I just save things into the string of mock logger here. I save things into written and then I assert that written actually has something. And this is what the string calculator looks like. That's the only difference that I've made. And notice that the difference is that it takes a logger. The logger is actually part of production code. The fake logger is part of test code. So the logger interface now abstracts away the knowledge from string calculator. So string calculator doesn't need to know what is the type of logger that it ## Related - [Depending on a logger](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_77) · The Art of Unit Testing, 3rd ed., ch. 4 The 3rd edition's section on depending on a logger, the same third-party logger problem used in this lesson. - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76) · The Art of Unit Testing, 3rd ed., ch. 4 Section introducing interaction testing, mocks and stubs, the definitions this lesson gives for fakes. - [One mock per test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec5) · The Art of Unit Testing, 2nd ed., ch. 4 The 2nd edition's section on one mock per test, the rule stated in this lesson. - [TDD Kata 2 - Interactions](https://osherove.com/tdd-kata-2) · osherove.com The Interactions kata extending String Calculator with a logger, forcing the mocks and stubs shown here. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19), ch. 1 - [Extracting a common interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74), ch. 3 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Constructor injection](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_72), ch. 3 - [The importance of differentiating between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_79), ch. 4 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Defining isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99), ch. 5 - [Entry points and exit points](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18), ch. 1 - [Dependencies, injections, and control](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_65), ch. 3 #### The Art of Unit Testing, 2nd ed. - [A simple handwritten mock example](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec3), ch. 4 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Interaction testing using mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4), ch. 4 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 - [Introducing stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1), ch. 3 #### osherove.com - [TDD Kata 1 - String Calculator](https://osherove.com/tdd-kata-1) - [Naming standards for unit tests](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html) - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) [Previous lesson Some Numbers](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/some-numbers/) [Next lesson Demo - Mock Objects](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/demo-mock-objects/) --- title: "Demo - Mock Objects" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/demo-mock-objects.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/demo-mock-objects/" tags: [] author: "Roy Osherove" description: "Lesson 9 of 21 in The Art of Unit Testing and TDD in Java (Day 2), 9:17. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Demo - Mock Objects 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 2 Lesson 9 of 21 Duration: 9:17 [Watch on YouTube](https://www.youtube.com/watch?v=XKlVqR164WY) A short demo showing how you can implement the [extract interface pattern](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)"), [constructor injection](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_72 "Constructor injection (The Art of Unit Testing, 3rd ed., ch. 3)") and hand written [mocks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") to solve our problem of controlling a 3rd party logger in a [unit test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)"). ## In this lesson Roy Osherove writes the add always calls logger test first, as if everything already existed, with a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") logger that saves the text in a public written field and is passed to the [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)")'s constructor. Because the other tests create the calculator through the make calc helper, the new constructor argument changes one place, where a fake logger is passed in as a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)"). He sees only the new test fail, makes add call the logger, and has to add throws Throwable to the tests, which he dislikes. ## Transcript 1,231 words [\[00:02\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=2s) So what I'm going to do is I'm going to create a new test. I'm going to start with scr from scratch. I'm going to write a test for [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)") that adds this dependency. And because this is test driven, I'm going to write my test before I do anything else. So I'm going to say test public void. I need to give it a good name. The name would be well add is the [entry point](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18 "Entry points and exit points (The Art of Unit Testing, 3rd ed., ch. 1)"). I might say always [\[00:32\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=32s) Because it always does something. It's not only when a specific something behavior happens. I want add to always call a logger. Then I can say calls logger. Okay. So now what we're going to do is we're going to pretend that the world that I would like to have in my code already exists. [\[01:07\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=67s) I'm going to write my test as if everything I need already exists. For example, I might say I would need a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") logger. I might say my fake logger. Now I I already wrote this for you guys in the demo. So you're going to see that this class is already written but I might say the fake logger just so that you don't see it in the IntelliSense fake logger [mock](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4 "Interaction testing using mock objects (The Art of Unit Testing, 2nd ed., ch. 4)") log equals new the fake logger. [\[01:40\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=100s) What else? We want to send the fake logger into the string calculator. I want to say string calculator equals I'm not going to use make calc anymore for this because when I use mock objects I want to have an explicit dependency. I want to be able to control the things that I send into the constructor. So I a don't want to use the [helper method](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6 "Building a test API for your application (The Art of Unit Testing, 2nd ed., ch. 7)") and b if I did choose to use the helper method it would become very very messy very fast. somehow it would have to save the mock object in a in a variable in the class and then I would have to figure out which it would become very unreadable. [\[02:16\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=136s) So I'm just going to make it right now direct. So I'm going to say new string calculator and I'm going to send in mock log. Of course this won't compile yet. But remember the point is to finish the test and say I think this is good enough. I understand the problem. this is how I want to test it and then I make everything work according to that. I might say scadd well this is the simplest I can think of and assert equals0 [\[02:55\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=175s) Into the logger mock log dot written or written and if I'm happy with that I can go ahead and create a class right above here because no one else is currently using this. If I see that I have multiple tests in multiple classes using those fake objects, I can then refactor and move it into a separate file. But right now, I want everything as close as possible to the test so that the serial killer doesn't need to go to my house and ask me what the hell that is. [\[03:29\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=209s) Class the fake logger implements logger. Now, logger doesn't exist yet, obviously, but I'm going to pretend it exists for a second. And here I'm just going to say public void write string text. I'm just going to say written is [\[03:59\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=239s) Equal to whatever the text is. So, this should be enough. Now I've actually gone ahead and created the slow logger and I do have an interface for logger which I wrote before. So what I'm going to do is I'm just going to connect to that. I'm just going to say logger import the class. [\[04:29\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=269s) But I do need a field here. Put it indirectly in this class and make it public. I don't need a getter and a setter because I want this code to be simple. There's no reason to hide and protect anything because this class is only for tests. Now I still have to go and add the parameter to the constructor. So I'm going to go ahead and say that the parameter type is logger. [\[05:02\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=302s) I'm going to call it log because the production code doesn't need to know that there is such a thing as mock objects at all. So it has to be purely abstract So that's the difference. Now remember this is [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)"). So I want my test after it compiles. I want to see it fail. So I'm not adding the functionality of calling the logger just yet. If I run this test [\[05:39\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=339s) I oh now there's a different compilation error and you're going to find this as well. And remember we talked about [maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)") of the test. Now I have 10 tests for string calculator but now I've added a constructor argument. Now I would have to change all my tests if I if all of them did new string calculator. Luckily I do have the make calc method right here which is which means I only have to change one place. Now the question is what am I going to send as an argument? The answer is I'm just going to send in a fake logger. [\[06:10\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=370s) But this time not no one is going to assert against it. Right? That means that for all the other tests they're just going to have a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1 "Introducing stubs (The Art of Unit Testing, 2nd ed., ch. 3)") logger. Just makes happy noises. doesn't do anything. So now very easily I can just say just send it a new the fake logger. That's it. If I run the test now they should all be passing except the one that I wrote. Where are you? Okay. [\[06:45\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=405s) And I can see now expected got zero but actual was nothing. So only my test the last test is failing which is what I wanted. So it took me only a few seconds to make all the other tests pass by sending in a stub and only in a single test am I using a mock object. Okay. And this is where the maintainability aspect comes in. Otherwise this would be hell now to go and send a new one in each one in each other test. So now I can go in and say okay let's go to the string calculator [\[07:22\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=442s) And when I call add I can say blah blah blah where is it well I just have to find somehow the default value right so I might say put it right there and say log write dot plus default value and of course this is bad because I'm repeating myself but I can refactor it later after the test passes [\[08:03\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=483s) Value to string let's see oh I need to handle the exception Okay. And that means probably that now I have to go and handle the exceptions in all the other cases. Now I have to go here. And this is the part that I hate coming from many different languages. Adding that throwable stuff is just horrible to me. I just don't like it. [\[08:34\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=514s) Now I have to go to all the tests and add the throw throws throwable whatever that means. Ah so you see you do it once and then you're done with it but it's still pretty horrible in terms of terms of usability and maintainability. Okay. And let's see if that would work. Start adding. [\[09:14\]](https://www.youtube.com/watch?v=XKlVqR164WY&t=554s) Are we done yet? Are we there yet? Thank you. ## Related - [A simple handwritten mock example](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 4 The 2nd edition's simple handwritten mock example, like the fake logger with a written field built in the demo. - [Constructor injection](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_72) · The Art of Unit Testing, 3rd ed., ch. 3 The 3rd edition's section on constructor injection, how the demo passes the fake logger to the calculator. - [Extracting a common interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74) · The Art of Unit Testing, 3rd ed., ch. 3 Section on extracting a common interface, the extract interface step behind the logger interface. - [Changes in the production code’s API](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_157) · The Art of Unit Testing, 3rd ed., ch. 8 Section on production API changes breaking tests, why the make calc helper keeps the constructor change in one place. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Entry points and exit points](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18), ch. 1 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [Maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8), ch. 8 #### The Art of Unit Testing, 2nd ed. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 - [Interaction testing using mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4), ch. 4 - [Building a test API for your application](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6), ch. 7 - [Introducing stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1), ch. 3 #### osherove.com - [TDD Kata 1 - String Calculator](https://osherove.com/tdd-kata-1) [Previous lesson Introduction to Mocks and Stubs](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/introduction-to-mocks-and-stubs/) [Next lesson Terminology](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/terminology/) --- title: "Terminology" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/terminology.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/terminology/" tags: [] author: "Roy Osherove" description: "Lesson 10 of 21 in The Art of Unit Testing and TDD in Java (Day 2), 0:56. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Terminology 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 2 Lesson 10 of 21 Duration: 0:56 [Watch on YouTube](https://www.youtube.com/watch?v=Bp2_Je2h-To) [Fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)"), [Stub](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1 "Introducing stubs (The Art of Unit Testing, 2nd ed., ch. 3)"), [Mock](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4 "Interaction testing using mock objects (The Art of Unit Testing, 2nd ed., ch. 4)"), Spy... what does it all mean? Let's talk about it. ## In this lesson Roy Osherove contrasts his simple terminology with the book xUnit Test Patterns, which gives many different names to things that look like other things. He only uses [fakes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)"): a fake that is asserted on is a [mock](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)"), any other fake is a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)"), and terms such as test spy can be learned later. ## Transcript 158 words [\[00:04\]](https://www.youtube.com/watch?v=Bp2_Je2h-To&t=4s) So I hope that makes some sense. Are there any questions so far? Okay. So just to remind you, we have the terminology we're using. Now there are many different terminologies. The the the one on the right is from a book called xUnit Test Patterns. It's a very good book, but the it assumes it gives many different names to all these things that look like other things. And I find that that's very confusing. So I just use a very very simple terminology. I I either have I I have [fakes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") and whether they're being asserted on or not, [\[00:40\]](https://www.youtube.com/watch?v=Bp2_Je2h-To&t=40s) That's the only difference. So if you assert on the fake, it's a [mock](https://osherove.com/blog/2005/6/30/the-mock-objects-elevator-speech.html "The Mock Objects elevator speech (osherove.com)"). Otherwise, it's a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)"). That's the only thing that you should know currently. And you can always learn about the other things like test spy, etc. But for now, if you just think about it like that, it should simplify your life very ## Related - [The importance of differentiating between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_79) · The Art of Unit Testing, 3rd ed., ch. 4 The 3rd edition's section on why to differentiate between mocks and stubs, the distinction this lesson keeps simple. - [Mocks and Stubs - The difference is in the flow of information](https://osherove.com/blog/2007/9/16/mocks-and-stubs-the-difference-is-in-the-flow-of-information.html) · osherove.com Roy's short explanation that mocks and stubs differ in the flow of information, a quick take on the same terms. - [Goodbye mocks, Farewell stubs](https://osherove.com/blog/2008/9/20/goodbye-mocks-farewell-stubs.html) · osherove.com Roy's post on fakes, mocks and stubs from his consulting, related to his choice to just say 'fake'. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 #### The Art of Unit Testing, 2nd ed. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 - [Introducing stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1), ch. 3 - [Interaction testing using mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4), ch. 4 #### osherove.com - [The Mock Objects elevator speech](https://osherove.com/blog/2005/6/30/the-mock-objects-elevator-speech.html) [Previous lesson Demo - Mock Objects](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/demo-mock-objects/) [Next lesson Mocks And Stubs](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/mocks-and-stubs/) --- title: "Mocks And Stubs" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/mocks-and-stubs.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/mocks-and-stubs/" tags: [] author: "Roy Osherove" description: "Lesson 11 of 21 in The Art of Unit Testing and TDD in Java (Day 2), 8:43. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Mocks And Stubs 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 2 Lesson 11 of 21 Duration: 8:43 [Watch on YouTube](https://www.youtube.com/watch?v=ZjBekTqSyuw) In this demo we look at a more detailed problem, where we would need a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1 "Introducing stubs (The Art of Unit Testing, 2nd ed., ch. 3)") and a [mock](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4 "Interaction testing using mock objects (The Art of Unit Testing, 2nd ed., ch. 4)") in the same test. ## In this lesson Roy Osherove adds a requirement that a web service is called when the slow logger throws an exception, for example when the disk is full on a machine. The [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") logger becomes a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") with a will throw method that sets the exception to simulate, and a fake web service becomes the [mock object](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") that the test asserts on. He writes the add when logger throws calls web service test with an out of memory error, and says the [test name](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html "Naming standards for unit tests (osherove.com)") tells you what to do when the fakes get confusing. ## Transcript 1,105 words [\[00:03\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=3s) Now let's take a more complicated scenario. Now the requirement is that I have a slow logger and a web service. Now the requirement is not that just you call a slow logger but when you call a slow logger and the slow logger somehow has an error then the web service gets called. So imagine this. I am the system administrator and whenever the disk is full on the machine, I need some kind of administrative web service to be notified that there's a problem with one of the machines. [\[00:42\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=42s) Make sense? So how do I test that web service gets called when slow logger throws an exception? Well, again, web service is something I don't have control over, but I can take control over by creating [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") objects. So again, I need to replace the web service with some kind of interface and the logger with an interface. I'll have a fake logger, but now I also need a fake web service. Now this time I'm going to make the fake logger throw an exception. [\[01:14\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=74s) I need to simulate an exception for some reason, right? But I'm not going to assert against it because I already asserted it gets called in a different test. What I'm going to do is I'm going to use it as a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)"). I'm going to make the stub throw an exception so it behaves the way I want, but I'm not going to assert against it. And then I'm going to assert that the web service got called. So in this case, the web service is the [mock object](https://osherove.com/blog/2005/6/30/the-mock-objects-elevator-speech.html "The Mock Objects elevator speech (osherove.com)"). And the fake logger is going to be our stub. [\[01:45\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=105s) And this is the ch these are the changes I'm going to do to the fake logger. I'm going to make it throw things, but I'm not I don't want to hard code the things it will throw. So, I'm adding a field called to throw and I'm checking whether to throw is null and if it's not, I just throw whatever is in there. And then I add a method called will throw. This is not part part of the interface, just part of fake logger. And that gives my test the ability to decide which exception I want to simulate. [\[02:26\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=146s) And then the web service will look exactly like the fake logger used to look. Just saves the values and then saves them and make them public so that we can check what was called. And then in my test look at the name add when logger throws calls the web service. So I do create the fake logger but then I say fake logger will throw and then I give it whatever error I want [\[03:00\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=180s) And then I create the fake web service and I create the [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)"). Now here I name it with twoep because it's part of the files. I wanted you to have versions of the files with all the differences, but it would be the original string out later and then I would send in the fake logger and the fake web service because I now have two dependencies. So I have added another argument to the constructor. Then I call add and I assert that I got back something into fake web service. [\[03:32\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=212s) I might want to name it mock web service in this case. Okay. Let's see that in a let's see that in the in the real code. So let's say I want to go back to my to my tests and again I want to add the feature where are I want to add the feature that it calls a web service. [\[04:02\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=242s) So what I'm going to do is I'm going to duplicate this and say add when logger throws calls web service. So I do need the fake logger but I want to say mocklog dot will throw new out of memory error [\[04:38\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=278s) And I want to send the string calculator something that that I can assert against. So let me rename the mock log to stub log [\[05:09\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=309s) And I want to send in a fake web service. I'm going to say the the fake web service mock service equals new the fake web service. And I'm going to send in the logger and the mock service here. And of course, this won't compile yet. But again, I want to finish my test first. So I that I I have all the pieces in my head lined up just right. [\[05:44\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=344s) If I don't understand my test, I'm going to be in deep trouble because at some point, especially when you just begin, you have these fake objects and you fake that and you mock that and then you forget what it is you're trying to test. And when that happens, you look at the name of the test and that will give you a map of what it is you're trying to do. Oh, this is what I this is the act part. This is the [arrange part](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "The Arrange-Act-Assert pattern (The Art of Unit Testing, 3rd ed., ch. 2)") [\[06:17\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=377s) And this is the assert part. So whenever you get confused, you look at the name of the test. it will tell you what it is you need to do if it's good enough. So I do need to assert that I got back let's say got dot out of memory error from mock service dot written [\[06:57\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=417s) And if all that's okay if If I like it, then I go ahead and I create the web service and I create an interface called web service. Then I add the constructor argument. I add the fake stuff and then I assert against it. But it would be the exact same pattern. The only thing that I need to do that I just want to show you is that how simple it is to make something throw something. [\[07:33\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=453s) Make it field. Then all I have to do in the write method is to say if error then throw the error. Okay, let's see. And then I have to add this of course. That's it. [\[08:05\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=485s) Now, yes, this becomes pretty heavy when you get to multiple things, but I want you to learn this technique because for simple stuff, sometimes this is actually easier than other things. And we'll get to mocking and [isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99 "Defining isolation frameworks (The Art of Unit Testing, 3rd ed., ch. 5)") later today. Questions? Okay, in that case I want you to open the following document and don't don't forget about working [in pairs](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html "How Do You Explain Pair Programming? (osherove.com)") from now on. Switching pairs from yesterday. Open the following exercise and do the first exercise. [\[08:37\]](https://www.youtube.com/watch?v=ZjBekTqSyuw&t=517s) Okay, only feature number one. You can take five minutes and get some coffee first, of ## Related - [Using a mock and a stub together](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec4) · The Art of Unit Testing, 2nd ed., ch. 4 The 2nd edition's section on using a mock and a stub together, like the throwing logger stub and web service mock. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2) · The Art of Unit Testing, 2nd ed., ch. 4 Section on the difference between mocks and stubs, to keep straight which fake is asserted on in this test. - [Having more than one mock per test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5) · The Art of Unit Testing, 3rd ed., ch. 5 Section on having more than one mock per test, the reason only the web service fake is the mock here. - [Multiple mocks, asserts, and hidden results](https://osherove.com/blog/2011/2/9/multiple-mocks-asserts-and-hidden-results.html) · osherove.com Roy's reply on multiple mocks per test and readable test names, the trade-off behind this lesson's test design. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [The Arrange-Act-Assert pattern](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2), ch. 2 - [Defining isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99), ch. 5 #### The Art of Unit Testing, 2nd ed. - [Introducing stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1), ch. 3 - [Interaction testing using mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4), ch. 4 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 #### osherove.com - [Naming standards for unit tests](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html) - [The Mock Objects elevator speech](https://osherove.com/blog/2005/6/30/the-mock-objects-elevator-speech.html) - [TDD Kata 1 - String Calculator](https://osherove.com/tdd-kata-1) - [How Do You Explain Pair Programming?](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html) [Previous lesson Terminology](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/terminology/) [Next lesson Isolation (Mocking) Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/isolation-mocking-frameworks/) --- title: "Isolation (Mocking) Frameworks" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/isolation-mocking-frameworks.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/isolation-mocking-frameworks/" tags: [] author: "Roy Osherove" description: "Lesson 12 of 21 in The Art of Unit Testing and TDD in Java (Day 2), 19:53. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Isolation (Mocking) Frameworks 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 2 Lesson 12 of 21 Duration: 19:53 [Watch on YouTube](https://www.youtube.com/watch?v=XPHayVzd99I) In this talk we learn about [Isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec1 "Why use isolation frameworks? (The Art of Unit Testing, 2nd ed., ch. 5)") and how they try to help us avoid some of the problems that hand written [mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_79 "The importance of differentiating between mocks and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") can create. Later we will also see sometimes Isolation frameworks hurt more than they help. ## In this lesson Roy Osherove explains that [isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99 "Defining isolation frameworks (The Art of Unit Testing, 3rd ed., ch. 5)"), which he prefers not to call mocking frameworks, automate [handwritten fakes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec3 "A simple handwritten mock example (The Art of Unit Testing, 2nd ed., ch. 4)"): they create [fakes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)"), save call arguments for verification and [simulate exceptions or return values](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec3 "Simulating fake values (The Art of Unit Testing, 2nd ed., ch. 5)"). He lists EasyMock, jMock, [PowerMock](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)"), JMockit and Mockito, and uses jMock's expectations and EasyMock's record and replay to show how strict fakes, which fail on unexpected calls, break tests for the wrong reason. He recommends EasyMock's [nice mocks](https://osherove.com/blog/2013/11/23/fifteen-things-i-look-for-in-an-isolation-framework.html "Fifteen things I look for in an Isolation framework (osherove.com)") and shows Mockito, which is non-strict by default, with verify, doThrow and parameter matchers such as any string. ## Transcript 3,014 words [\[00:08\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=8s) Up until now we've done things in a very manual way and it was pretty easy but things become slowly problematic as you get more and more code. So when you do [handwritten mock](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec7 "The problems with handwritten mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") objects and [stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") at the beginning it's pretty easy but as it gets as you get for example more parameters more method calls more methods per interface things become very very unmaintainable very quickly and you would end up with at some point with a custom library that you would have built that saves values and allows you to assert against them because you would end up with it because you would keep using these [fakes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") over and over and you would just have these helper methods become more and more generic. [\[00:55\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=55s) And this is basically the problem that [isolation frameworks](https://osherove.com/blog/2008/12/3/isolation-frameworks-lessons-from-the-wild.html "Isolation frameworks – lessons from the wild (osherove.com)") try to solve. Now when I say isolation frameworks I mean what many people call mocking frameworks but I don't like to call them mocking frameworks because we know that the word [mock](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") means something specific and a lot of times you would use these frameworks also to create stubs. So the word mocking framework is actually very confusing and it also could lead to everyone using mock objects instead of using stubs. [\[01:30\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=90s) And you should have less mock objects and stubs in your code. If you're going to if you're going to use them, you might as well have less than more. So I call them isolation frameworks because they isolate the [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") from the dependencies that it cannot control. In our examples, we isolated [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)") from web service and logger. And what these frameworks really allow us to do is to do automatically what we just did in a handwritten way. [\[02:04\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=124s) They allow us to create fakes without having to create a class for those fakes. They allow us to save the call arguments from those fakes and then assert against them later and verify that they were called. They allow us to build in to have a built-in way to simulate things like exceptions and custom return values because tomorrow maybe what we'll do is instead of return an exception from logger maybe what we'll want to do is to return from a method a negative number or a string or simulate anything back into our our application [\[02:38\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=158s) And isolation frameworks provide usually very easy way to accomplish that. So they have two APIs. They have API for arranging how the behavior of the fake object will be and they have an API for verifying whether the mock object was called. Now isolation frameworks have been around for a long time and that means that they also ha in the in that in the last I would say six years we've the industry has been learning a lot about how to properly use mock objects and stubs and we have we've learned some practices of things that we should and shouldn't do. [\[03:15\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=195s) For example, having multiple mock objects in the same test is not a great idea because that's basically [multiple asserts](https://osherove.com/blog/2005/4/14/try-to-avoid-multiple-asserts-in-a-single-unit-test.html "Try to avoid multiple asserts in a single unit test (osherove.com)") on different requirements and if one of them fails, the others never execute. But the older isolation frameworks, some of them still do not support a lot of these values and they allow you to do very easily things that will hurt you and and in terms of [maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)") and [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)"). What I'm going to do now, I'm going to show you some examples of how the APIs of these frameworks exist work. [\[03:47\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=227s) I'll talk a little bit about the model of how they they expect you to use them and pros and cons about those models. The the things we'll talk about during this course, not all of them today, is EasyMock, jMock, PowerMock, JMockit and Mockito. Specifically today I'm going to show you EasyMock jMock and Mockito and tomorrow we'll also focus on JMockit and PowerMock. [\[04:22\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=262s) And there's a difference between those two frameworks and the other ones in that they are called [unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)"). They allow you to fake things that you usually wouldn't be able to do if you just write your own code and inherit from an interface. For example, static methods. We'll start touching on [faking static methods](https://osherove.com/blog/2012/7/8/faking-static-methods-in-moq-fakeiteasy-and-nsubstitute-migh.html "Faking static methods in Moq, FakeItEasy and NSubstitute might be closer than imagined (osherove.com)") tomorrow with the framework. But today, if time allows, we'll also get to a point where we learn how to refactor code that has static methods so that we don't even have to use these frameworks unless we have to. [\[04:55\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=295s) So that means that in this course, we're going to learn two different ways to accomplish each thing either through refactoring or through a framework. It will give us choice and will also allow us to understand either what those frameworks are doing or the trade-offs that we have between readability, maintainability and ease of use of [testability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec1 "Why should I care about testability in my design? (The Art of Unit Testing, 2nd ed., ch. 11)") of the code. So first I want to introduce jMock. jMock is basically I think it's the oldest isolation framework. [\[05:28\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=328s) To use jMock you would create an object called mockery which I find kind of hilarious and and then you would ask the mockery object to mock a logger.class class. And notice that there isn't a word called stub. We just say mock. So even if you're going to use it as a stub, it's going to be called the mock object, which already is confusing. And one of the things that I don't like about the old style of these isolation frameworks is that a lot of them have the word mock everywhere, and they don't allow you to say whether something is a stub or not. [\[06:03\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=363s) And a lot of them also by definition are what I call strict. Well, not me, but a lot of other people. So, what does a strict framework mean? Here's an example of a very simple test. There is no assert here yet because I haven't explained how to work with the framework. But I want you to understand what the difference between a strict and a nonstrict isolation framework means because a lot of the old ones are very strict and a lot of the new ones are [non-strict](https://osherove.com/blog/2013/11/23/fifteen-things-i-look-for-in-an-isolation-framework.html "Fifteen things I look for in an Isolation framework (osherove.com)"). [\[06:34\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=394s) And we want nonstrict. Okay? We want relaxed frameworks. So what does a strict framework mean? It means that if I create a fake object of the of of the [logger interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)") and somewhere in the add method I call a method on logger and I didn't specify exactly that this method would will be called or might be called somewhere above this test will actually fail. [\[07:07\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=427s) I will get an exception even though I didn't assert on anything that says you called an unexpected method on the logger. Okay, I will actually get an exception right here because I I didn't tell the isolation framework what's going to happen to the mock object. Now, it used to be that this was like a pretty good practice. Nobody realized this is actually hurting our tests. [\[07:37\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=457s) But in reality, this is what I have to do to make this test pass. I have to to to create these three lines called context checking new expectations. I say I'm allowing the log to be called with write with any string. And now this test will not fail. I haven't yet asserted on anything. But I have to do this for this test not to fail at the very least. [\[08:09\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=489s) Now, that doesn't look like a pretty bad thing so far, but I want you to think about what's going to happen next month when I work on something in the code that has nothing to do with this feature of calling the logger and I need to add some more logging or I call a different method on the logger that doesn't do logging. it initializes something or anything really. And suddenly I have maybe three, four or 50 tests that have a fake logger, not even a mock object. [\[08:44\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=524s) And all those 50s tests start screaming at me. You didn't tell me this method is going to be called. Now, that has nothing to do with the fact that the features that they originally test actually work. I'm just adding an extra call. Or you know what? Maybe I'm optimizing and I'm removing an extra call. In either case, those tests will actually stop working even though I didn't even assert that those mock objects or those fake object will get called because by definition in those in this framework, every fake object is a mock object. [\[09:19\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=559s) Okay, I have to specifically say allowing for this to start behaving like a stub. And a stub is something that makes happy noises. It just allows me to run the test and test something else. It doesn't cause problems unless I specifically tell it to cause problems. That means that for every new call or anything, I have to go back to all the tests that use that fake object and add a line to allow that call to happen, which makes my test basically cement. [\[09:52\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=592s) Every time I have to change something in production code, I'm going to have tests failing telling me that the mock objects were not configured correctly. So the test will fail for the wrong reason. And that's where strict is actually bad for you. That's why I wouldn't recommend working with a jMock. Even though it's one of the oldest and has a nice API, the fact that it is strict by default is a problem. Now how would I verify just in case? [\[10:22\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=622s) I would change allowing to at least one. Now notice that this that this is basically my test for verifying that the logger was called. There is no assert at the bottom and the bang here will not occur. By the way, this what what's going to actually happen is that at the end of the test, there will be a hidden assert running inside jMock that will verify that this was called at least once. [\[10:55\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=655s) But this breaks the structure of arrange act assert. Here the arrange and the assert are in the same location, which means that the test is less readable. And that's also something that's very common in the old style of frameworks, isolation frameworks, is that they don't allow you to very easily obey the idea of arrange act assert. So the tests are less readable and usually very very chatty [\[11:30\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=690s) So the idea of allowing versus expecting is what makes me have a stub versus a mock. But I still have to have that extra line. Let's talk about EasyMock. Easy is a framework that's also pretty old. And this framework has a very interesting API. It it uses what's what is called record and replay. And the idea is that for any object that you create, for example, you say create mock of this logger. Of course, this could be a stub. [\[12:02\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=722s) Before you actually if you want to set any expectations on the object, you record those expectations at the [arrange part](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "The Arrange-Act-Assert pattern (The Art of Unit Testing, 3rd ed., ch. 2)") and then you call replay on that object and from that moment on that object will either return the values you told it to return or it will expect the values you told it to expect. So in this case this is an example of the same strict by default. There is no assert yet. I didn't record anything. I still have to call replay which is just an one extra line that I have to do. [\[12:34\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=754s) So it looks weird. And create mock by default creates a strict mock. So this line will fail as well because somewhere in here I'm going to call the logger and I'm going to get an exception that says hey you didn't tell me that that the logger was going to get called. Sorry. So to do to actually change it, what I would have to do is to use a method called create nice mock. Okay, that's the mock that you want or the fake object that you want. [\[13:07\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=787s) That's the he >> sorry. >> This is the still EasyMock API. >> It has a create mock and create nice mock. We want create nice mock. If you're going to have to use EasyMock, create nice mocks. Okay, those are the ones that act like hippies. you know they say oh you can call me as many times as you want dude I don't care but at the end of the day we can actually ask whether something was called and it will tell us so nice mocks allow us to have more maintainable test because if I add or remove calls tomorrow as long as the feature still works I will not have to change the test it will not break [\[13:44\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=824s) Okay I want to show you what things look like with Mockito hold on. Mockito. Okay, so here is the same test with Mockito. Now, what I like about Mockito is that it's what I call one of the new frameworks. [\[14:17\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=857s) And by one of the nice features about the new framework is that they usually obey the idea of non strict by default very easily. So unfortunately in Mockito everything is still called a mock which sucks. I would rather have the word fake here. But nevertheless if I want to have a fake logger I would just say mock logger class. I would call it. And if that's all I did, if I was just on this line here, my test wouldn't break if I called it. [\[14:53\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=893s) Okay? Because it's nice by default. If I want to verify that in that something got called, I would say verify mock log, write, and then just pass it the string. Okay, so I verify I pass it the the fake object and I basically call this method with a string of some sort. Let's see the more complicated case. [\[15:30\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=930s) So when logger throws it calls the web service. So here I'm creating a stub logger using the mock method. You see how confusing that is. And I and if I want to simulate something I will use the do throw method. And the reason I have to use do throw is because this is a void method. If this was returning something I would do it at the end of the API. But for now just learn about this. Do throw new out of memory error when stub logger.write. [\[16:05\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=965s) Okay. For nonvoid methods I would just start with when and then I would say return then return blah blah blah or then throw. So do throw out of memory when write is called. And notice that here I'm saying that it could be any string. This is what's called a parameter matcher. Instead of saying a hard-coded string and then having to change it if the production code changes, I just say dude, it's any string. [\[16:35\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=995s) What's nice about these matchers that I can also use them here. I can say, was this called with any string? Then I wouldn't care about the string. I can also call it with a string that contains something, which is a more maintainable way. If you do have to look for a string, it's better to look for something in the string. Otherwise, you might have new lines and tabs. Yes. >> Can you refer back to things that you that you set up? You said you're any [\[17:05\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=1025s) Can you can you quickly verify that the same string for example got out or got called. >> So I'll show you how to do verify. This is right now this is simulation. >> Okay. This is how I would verify. verify that the mock web service.write was called with something that contains out of memory error. Does that answer your question? >> Because I if I can say that [\[17:36\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=1056s) Remember this is a stub. I don't want to assert anything on it. >> Yeah, that's probably >> okay. I'm not testing what that output is. >> No, you don't. You do not usually for maintainability sake, you do not want to test what's in here. And the reason is because the more specific you are, the more you will have to change your test later. And the more specific you are, the more it means that you're setting up something very complicated. And tests should be simple. [\[18:07\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=1087s) Remember, you're just testing one small scenario. In that small scenario, it your stub logger might as well return any an error for anything unless you specifically know that some other objects might be calling it and then you have to take care of that and say look but if I get this then don't throw an exception. Yes, [\[18:37\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=1117s) >> the question about the annotations. Yes, you're using >> you're using the annotation the annotation style. Yeah, >> instead of the >> instead Yeah, you could use both. I for one think that naming the variable correctly and just using the simplest API that could possibly work makes the test more readable. The more annotations you have, the more you have to refer back to the top of the test. U but this is more of a stylistic choice. I don't really mind too much if you use annotations at the top of the test. I specifically don't like that style, but I don't have too many reasons not to like it. [\[19:11\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=1151s) It's more about personal choice. What I would recommend is whatever style you choose, you be consistent throughout the team. So that it's easy to read the test by that someone else wrote. So we have the arrange, we have the act, we have an assert. And that's one of the things to like about things like Mockito Okay, I want you to go back to the exercise and do the exercises and features until you see something that says wait for demo or anything like that. [\[19:47\]](https://www.youtube.com/watch?v=XPHayVzd99I&t=1187s) Okay, and then just raise your hand and call me when that happens. But you have to do it [in pairs](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html "How Do You Explain Pair Programming? (osherove.com)"), remember? ## Related - [Defining isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99) · The Art of Unit Testing, 3rd ed., ch. 5 The 3rd edition's section defining isolation frameworks, the tools introduced here to replace handwritten fakes. - [Fifteen things I look for in an Isolation framework](https://osherove.com/blog/2013/11/23/fifteen-things-i-look-for-in-an-isolation-framework.html) · osherove.com Roy's checklist for isolation frameworks, starting with strict vs non-strict by default, as compared in this lesson. - [Isolation frameworks – lessons from the wild](https://osherove.com/blog/2008/12/3/isolation-frameworks-lessons-from-the-wild.html) · osherove.com Roy's lessons from comparing isolation frameworks in class, and why he stopped saying mocking frameworks. - [Advantages and traps of isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec6) · The Art of Unit Testing, 2nd ed., ch. 5 The 2nd edition's section on advantages and traps of isolation frameworks, such as tests breaking for the wrong reason. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [The importance of differentiating between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_79), ch. 4 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8), ch. 8 - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 - [Extracting a common interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74), ch. 3 - [The Arrange-Act-Assert pattern](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2), ch. 2 #### The Art of Unit Testing, 2nd ed. - [A simple handwritten mock example](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec3), ch. 4 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Simulating fake values](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec3), ch. 5 - [Constrained and unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1), ch. 6 - [Why use isolation frameworks?](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec1), ch. 5 - [The problems with handwritten mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec7), ch. 4 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 - [Why should I care about testability in my design?](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec1), ch. 11 #### osherove.com - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) - [TDD Kata 1 - String Calculator](https://osherove.com/tdd-kata-1) - [Try to avoid multiple asserts in a single unit test](https://osherove.com/blog/2005/4/14/try-to-avoid-multiple-asserts-in-a-single-unit-test.html) - [Faking static methods in Moq, FakeItEasy and NSubstitute might be closer than imagined](https://osherove.com/blog/2012/7/8/faking-static-methods-in-moq-fakeiteasy-and-nsubstitute-migh.html) - [How Do You Explain Pair Programming?](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html) [Previous lesson Mocks And Stubs](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/mocks-and-stubs/) [Next lesson Capturing Mock Arguments](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/capturing-mock-arguments/) --- title: "Capturing Mock Arguments" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/capturing-mock-arguments.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/capturing-mock-arguments/" tags: [] author: "Roy Osherove" description: "Lesson 13 of 21 in The Art of Unit Testing and TDD in Java (Day 2), 4:36. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Capturing Mock Arguments 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 2 Lesson 13 of 21 Duration: 4:36 [Watch on YouTube](https://www.youtube.com/watch?v=gsuCaSHnKak) A short demo showing how you can capture the arguments sent to a [mock object](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") created with Mockito. ## In this lesson Roy Osherove shows Mockito's argument captor for checking that a trace message with specific attributes was sent to the logger, by capturing the argument in a verify call and asserting on its value. He calls this clumsy and compares it with a [handwritten fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec3 "A simple handwritten mock example (The Art of Unit Testing, 2nd ed., ch. 4)") class, which has to change whenever a method is added to the [logger interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)"). A participant suggests implementing equals on the trace message, which he says can be the most readable way when the object is simple. ## Transcript 665 words [\[00:03\]](https://www.youtube.com/watch?v=gsuCaSHnKak&t=3s) I want to show you quickly something. One of the exercises requires you to check that an a trace messages being sent to the logger with specific attributes. I want to show you how you can achieve that with Mockito. So Mockito has a special object called argument captor to capture arguments. And the way you use it is that you wait until the assert phase and then you create an argument captor of type trace message. [\[00:36\]](https://www.youtube.com/watch?v=gsuCaSHnKak&t=36s) So you declare it and you say give me an argument captor for class trace message.class and then you do a verify but instead of just saying write message with the with an object you say write message and you send in the the the argument captor.capture. capture and then once you have that you have you can get the value from the argument by saying get me the value put it in the object back you that and one now you'll have the object that was called with the values then you can assert on the severity or on the message of the object [\[01:15\]](https://www.youtube.com/watch?v=gsuCaSHnKak&t=75s) Now if that seems clumsy it's because it is it might be easier to write a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") class of your own to just capture the argument could be just as an idea. So it would be good to experiment both with this approach and by creating a class that inherits from the slow logger or implements the [logger interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)") whichever you want. Okay, just realize that the more [handwritten fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec7 "The problems with handwritten mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") classes that you have, the more you will have to change them every time you add a method to the interface of the logger. [\[01:53\]](https://www.youtube.com/watch?v=gsuCaSHnKak&t=113s) That creates future [maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)"). But here it definitely costs us with some [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)"). Okay, so both of these methods are not great. One of them is not great in the future. The other is not great now. But it is a trade-off. There is no good way. There is only two bad ways to do it. Okay, if you want to verify an object on the [mock object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4 "Interaction testing using mock objects (The Art of Unit Testing, 2nd ed., ch. 4)"), [\[02:23\]](https://www.youtube.com/watch?v=gsuCaSHnKak&t=143s) That's one of the only ways to do it. Now, it could be a design issue. Maybe we don't want to do that. Maybe we we could capture things and save them as public fields. But I would venture to say that if this if we're truly tr trying to send an object, we could try to beautify this code by doing maybe [helper methods](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6 "Building a test API for your application (The Art of Unit Testing, 2nd ed., ch. 7)"), something like that. Extract all this into a method and say verify the call and get back the argument. [\[02:53\]](https://www.youtube.com/watch?v=gsuCaSHnKak&t=173s) We could try to refactor this to be a bit more readable. Okay. Questions, answers. What's your answer? >> The whole equals in the fake trace message, not fake trace message. >> Yeah. Oh, yeah. Of course, that's another way. Of course, I forgot about that. You could say that you might verify [\[03:28\]](https://www.youtube.com/watch?v=gsuCaSHnKak&t=208s) Mock log dot write message with a new trace message with severity and the message >> fails at first because the objects are not the same >> and first it fails because the objects are not the same instance. So you have to implement equals right. >> That's right source. >> Yeah. So this would actually yeah that would be a third way I completely forgot about I apologize because I am also stuck in my head about isolation frameworks. [\[04:03\]](https://www.youtube.com/watch?v=gsuCaSHnKak&t=243s) But this would be a good way to do things if you have an object pre-prepared with all the values that you want. But you have to remember that when you do this you're basically asserting on all the attributes of the object. If you have 20 of them, you have to set up 20 of these attributes. If you do this approach, you can pick and choose which attributes you care about. So it's always a trade-off. But here, yes, if you implement equals, that might be the most readable way if the object is quite clean and simple. [\[04:33\]](https://www.youtube.com/watch?v=gsuCaSHnKak&t=273s) >> Good. Good answer. ## Related - [Simulating fake values](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 5 The 2nd edition's section on simulating fake values with a framework, including checking arguments passed to fakes. - [The problems with handwritten mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec7) · The Art of Unit Testing, 2nd ed., ch. 4 Section on problems with handwritten mocks and stubs, such as changing the fake whenever the interface grows. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Extracting a common interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74), ch. 3 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8), ch. 8 - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 #### The Art of Unit Testing, 2nd ed. - [A simple handwritten mock example](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec3), ch. 4 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Interaction testing using mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4), ch. 4 - [Building a test API for your application](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6), ch. 7 [Previous lesson Isolation (Mocking) Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/isolation-mocking-frameworks/) [Next lesson Extract And Override Refactoring](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/extract-and-override-refactoring/) --- title: "Extract And Override Refactoring" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/extract-and-override-refactoring.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/extract-and-override-refactoring/" tags: [] author: "Roy Osherove" description: "Lesson 14 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 13:35. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Extract And Override Refactoring 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 3 Lesson 14 of 21 Duration: 13:35 [Watch on YouTube](https://www.youtube.com/watch?v=k0g4mi5_iVE) In this talk we learn about the [Extract and Override Refactoring](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html "Mock Objects vs. \"Inherit & Override\" (osherove.com)"), and why it is one of the coolest things you should know. ## In this lesson Roy Osherove separates [constrained isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev2sec1 "Constrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)"), which cannot override static or private methods, from unconstrained ones such as [JMockit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") and PowerMock, which can [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") them. Without them, he applies [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") to a [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)") that calls a static logger: the call moves into a protected call logger method, which a [testable subclass](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95 "Partial mocks (The Art of Unit Testing, 3rd ed., ch. 4)") in the test overrides to save the text in a public field. He also explains [seams](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec4 "Refactoring your design to be more testable (The Art of Unit Testing, 2nd ed., ch. 3)"), keeping logic out of the extracted method, and starting [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") with [integration tests before refactoring](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_225 "Writing integration tests before refactoring (The Art of Unit Testing, 3rd ed., ch. 12)"). ## Transcript 2,051 words [\[00:08\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=8s) >> Okay. >> Hello. So up until now we've dealt with standard things instance methods, virtual methods, things that we can override. But what happens when we we we come across things that we can't easily override? we can't replace the instance of things because maybe a class doesn't receive an interface. Maybe a class uses static methods of a logger. Well, this is where we start looking at other ways to test our code. [\[00:44\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=44s) Now, before we do this, I want to mention that there are two types of [isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99 "Defining isolation frameworks (The Art of Unit Testing, 3rd ed., ch. 5)"). There are constrained and [unconstrained isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)"). Now, the [constrained isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev2sec1 "Constrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") basically work like we've done so far. We create a class that inherits from something then we override the methods we care about. But also that means that those frameworks have the same constraints that we have as developers. We cannot override a static method for example. We cannot override a private method or a constructor [\[01:17\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=77s) Unless we unless we have some kind of special tool. Otherwise we have to override to sorry to refactor things. So unconstrained frameworks allow us to basically test our code without changing it. Those include JMockit which is both a test framework but it can also run within [JUnit](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)") and it also includes the ability to fake static methods, private methods and other things and PowerMock which is an addition [\[01:50\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=110s) An additional framework that you can use within EasyMock or Mockito and I'm going to explain about those and how you can use them but first I want to show how we don't have to use them if we don't have to. So I'm going to show a very common technique to refactor your code even if it uses static methods. And we're going to practice to use this technique. I'm calling it [extract and override](https://osherove.com/blog/2012/5/16/test-driven-validation-logic-with-extract-override.html "Test Driven Validation Logic with Extract & Override (osherove.com)") so that we can learn how to refactor our code [\[02:20\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=140s) From its dependencies. So extract and override is basically a way for us to look at something that calls something we don't control and then extract the call to that something. Let's say it's a logger and make it into a separate method that just contains the call to that logger and then we inherit the class the actual class that contains the call. So if the class is [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)") and it calls a logger, we actually inherit [\[02:51\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=171s) In our tests from string calculator and we override the virtual method we just extracted. It sounds kind of complicated, but it really isn't. So let's say that we have this class. It's a class called static logger. It has a static method and we obviously can't use it. And what we'd like to do is to prove that is to prove that we actually call static logger when we should. [\[03:23\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=203s) So in our what I'm going to show you is a class called string calculator with statics. And in there there is already a call to static logger. So now we're kind of getting into [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10 "Working with legacy code (The Art of Unit Testing, 2nd ed., ch. 10)") land a little bit. How do you prove that maybe there is a bug in the call? Maybe there's a missing space or an extra space that shouldn't be there. And we want to prove that before we change the code in the call to the static logger. So one way we can do this without using things like PowerMock is by extracting just that line where we call static logger into its own little method. [\[04:01\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=241s) Before we use PowerMock, let me just show you how we can achieve this without things like power. So here we have the class and this is the line that we care about static logger.write but I want to make this class more testable. Obviously I cannot test that static logger was called with regular methods. So what I'm going to do is I want to be able to write this test [\[04:31\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=271s) Add always calls the static logger. That's what I want to prove. Maybe it doesn't, maybe it should, but I'm not even sure where to start. So, I'm going to make it testable first. And when we deal with legacy code, some of the rules of [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") don't make sense anymore. For example, sometimes you have to refactor your code before you can test it as a [unit test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)"). But of course, before you can refactor your code so you can make it testable, you have to have some kind of [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)") so that you know you didn't break anything by refactoring to make it testable so that you can test it. [\[05:03\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=303s) See, it's a very simple idea. You start with integration test so that you can refactor your legacy code and then you can add unit tests. Okay. So what do I do? I just select this line and I extract the method. Now notice that the string that I sent to the logger is not I took the int and the string and I made it into a single parameter because what I don't want to happen is that in the virtual method I'm going to create I don't want there to be any logic whatsoever [\[05:39\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=339s) Because if there is logic I'm going to be overriding that in my test. So I won't be able to test that logic. So what I what I'd like to do is to also know that the text being sent is correct. So I don't want to have any logic in my tests and I want to not override any logic in my tests. So I'm going to make the extract method the simplest method I can think of. So I'm just going to call it call logger. [\[06:11\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=371s) So I have this method call logger. Now I have this call. I'm going to make it protected so I can override it. And that's basically it. You know this is a very very simple method. I have call logger here. And the idea of refactoring is changing the code without changing the functionality. And the code does exactly the same as it did before. The only difference is that now I have a way to to test it. So what I've done actually is created what what's called a [seam](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec4 "Refactoring your design to be more testable (The Art of Unit Testing, 2nd ed., ch. 3)"). [\[06:45\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=405s) A seam is when you have for example fabric and you want to connect two pieces of fabric. So all our clothes are made of many many seams. It's where things connect to each other. So a seam is also where you can inject or replace or override dependencies in your tests. The more seams you have in your code, the more testable it is basically. So here we've created a seam because we have a method that is virtual by default that only handles the dependency. [\[07:16\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=436s) Yes of course I could have overridden parse single number but then I wouldn't be able to test all the logic inside it. So I don't want to override that. I want to only create a method that I override that will [break the dependency](https://osherove.com/blog/2005/8/23/issues-in-breaking-dependencies-for-unit-testing.html "Issues in breaking dependencies for unit testing (osherove.com)") to the static logger. And now just like I did with a [mock object](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)"), I can assume that I have this what's called a mock method. So I assume that if the method got called, then the static logger got called. So how do I do that? If I go to my test, the first thing I'm going to do is that in my test class, I'm going to create a new class and I'm going to call it testable [\[07:53\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=473s) String calculator with statics because that's the name of a class that I'm overriding. I'll say I'm extending string calculator with statics. Now this is the first time we've done this in all of this course is that we actually inherit from the class we are about to test. But we are going to inherit all the implementation of that class and we're only going to override a single method in that class. [\[08:30\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=510s) So here I might say override and then paste that in. And now I can override that method. And notice that I'm using the override annotation here. This is just an optional annotation that I can use so that my compiler will tell me if I got the name of the method wrong for example. So if I do this I can see a little error here. [\[09:01\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=541s) There is no such method. It's just a helper for me. Okay. So I override this and now I'm going to treat it just like we did with all the fake classes we hand written before. I'm going to take the text. I'm going to say written equals the text we just got. And what is written? Let's just make it a field on the class. Make it public so that we can assert against it. That's about it. [\[09:32\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=572s) So now we have this whole class and that's the class we're actually going to use in our tests. So now in my test I'm going to create a testable string calculator with statics new testable [\[10:03\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=603s) And once I've created I can basically say let's see did I get it wrong? Yeah, I should have said string testable mistake. Now the next thing is I'm actually going to call SC.add because that's my requirement. And last thing I have to do is just assert equals that I get back one to [\[10:34\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=634s) The written. So this is almost like closing a circle. It goes back to when we just started with using our own little fake classes. Only this time the fake class is the real class, but the only thing fake about it is a single method. Everything else is the real implementation. So we break the dependency on the static logger by overriding the method that calls it. And so if the field has one, we can assume that the static logger method actually got that text because there is very little logic that we override. [\[11:12\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=672s) We can be pretty certain that things are okay. This is called extract and override questions. answers. Does anyone want me to repeat this? >> Yeah, the call logger. This is what it looks like. >> Yes, this is the extraction and this is what it looks like. >> You had to do the extraction because you couldn't override the static right directly. [\[11:42\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=702s) That you can override the call. >> I had to do the extraction because not because I couldn't override the call to parse single number but I couldn't override a call to a static logger. You cannot override a call to a static method because there is nothing to replace. There is no instance of anything. So whenever we have something like that and by the way this works for anything creating a new logger creating a static logger calling a database anything you can extract the call to that dependency as simple as possible and then override that method that allows you to break anything you want. [\[12:19\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=739s) Now, this is so easy to do once you get used to it that I call this extract an override because it's you're like addicted to it. Once you go into legacy code, this is much easier to do than extracting an interface into the system because it's much less work. Extracting an interface into the system makes you extract a whole new class. This allows you to just override a single method. This is also good for cases where you want to have a method that has a lot of logic, a lot of checking like validation. [\[12:51\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=771s) You want to check that the person name is that and that the XML is this and the database is there and all these five things maybe have to be true. And you can override each of them make them each virtual methods and then override them like flags and say create a testable version where this flag will return true. This flag will return false. This flag will return true. Let's see what happens. So you can play with it in a very very easy way. But you have to learn how to do it first. More questions. [\[13:27\]](https://www.youtube.com/watch?v=k0g4mi5_iVE&t=807s) Okay. So we're going to continue from where we left off yesterday. But from the part that where it says after demo for extract and override. ## Related - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5) · The Art of Unit Testing, 2nd ed., ch. 3 The 2nd edition's section on variations on refactoring techniques, which includes extract and override. - [Mock Objects vs. "Inherit & Override"](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html) · osherove.com Roy's post comparing mock objects with inherit and override, the subclass-and-override technique taught here. - [An object-oriented partial mock example](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4) · The Art of Unit Testing, 3rd ed., ch. 4 The 3rd edition's object-oriented partial mock example, overriding a method in a testable subclass. - [Test Driven Validation Logic with Extract & Override](https://osherove.com/blog/2012/5/16/test-driven-validation-logic-with-extract-override.html) · osherove.com Roy test-drives validation logic with extract and override, another worked example of the refactoring. - [Writing integration tests before refactoring](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_225) · The Art of Unit Testing, 3rd ed., ch. 12 Section on writing integration tests before refactoring, the advice for starting with legacy code here. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Partial mocks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95), ch. 4 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Defining isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99), ch. 5 - [The xUnit frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39), ch. 2 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 #### The Art of Unit Testing, 2nd ed. - [Constrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev2sec1), ch. 6 - [Constrained and unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1), ch. 6 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Refactoring your design to be more testable](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec4), ch. 3 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10), ch. 10 #### osherove.com - [TDD Kata 1 - String Calculator](https://osherove.com/tdd-kata-1) - [Issues in breaking dependencies for unit testing](https://osherove.com/blog/2005/8/23/issues-in-breaking-dependencies-for-unit-testing.html) [Previous lesson Capturing Mock Arguments](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/capturing-mock-arguments/) [Next lesson Faking Time](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/faking-time/) --- title: "Faking Time" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/faking-time.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/faking-time/" tags: [] author: "Roy Osherove" description: "Lesson 15 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 5:46. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Faking Time 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 3 Lesson 15 of 21 Duration: 5:46 [Watch on YouTube](https://www.youtube.com/watch?v=jpvaPGdV8ts) Learn a simple technique to [handle time in your tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec5 "Cross-cutting concerns injection (The Art of Unit Testing, 2nd ed., ch. 7)"), and in your production code. ## In this lesson Roy Osherove explains why tests should not depend on the [current date and time](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_64 "Stubbing out time with parameter injection (The Art of Unit Testing, 3rd ed., ch. 3)"), and why [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") or a [time provider interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)") in every constructor does not suit a [cross-cutting concern](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec5 "Cross-cutting concerns injection (The Art of Unit Testing, 2nd ed., ch. 7)") like time. Instead he uses a static time provider class in the production code that tests can force to a given time and reset afterwards, for example in an after method. For the machine name in the next exercise he suggests extract and override. ## Transcript 1,006 words [\[00:02\]](https://www.youtube.com/watch?v=jpvaPGdV8ts&t=2s) Okay, let's talk about [controlling time](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec5 "Cross-cutting concerns injection (The Art of Unit Testing, 2nd ed., ch. 7)") and space. One of the requirements in the document that we have is that we want to manipulate the current time. We want to format a string with a date. Now, the problem with dates are that they keep changing. So if we actually use the current date and time in our tests, what's going to happen is that every time we run the test, it's actually going to be a different test. We want our test to be repeatable always so that we can have the [safe green zone](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec2 "Mapping out tests based on speed and type (The Art of Unit Testing, 2nd ed., ch. 7)"). [\[00:36\]](https://www.youtube.com/watch?v=jpvaPGdV8ts&t=36s) If you remember, a safe green zone is when you right click and run and all the tests should be green no matter what, as long as the production code is okay. We only want them to fail when the production code is okay, not when the time changes. So instead what we want to do if we want to implement something like this but we want to test it there are several ways to get around this. For example we can create a virtual method that gets the current time. [\[01:07\]](https://www.youtube.com/watch?v=jpvaPGdV8ts&t=67s) So we can say extract method oops selected block. Oh yeah, of course. Extract method get time. And then we can make this virtual protected sorry. And then we can override it and return whatever time we want in our tests. That looks kind of easy. [\[01:38\]](https://www.youtube.com/watch?v=jpvaPGdV8ts&t=98s) However, that could be a bigger problem than you think. And the reason is because time is usually crosscutting. Everyone uses it. And so what that will require of you is that every class that uses time, you're going to have to [extract and override](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html "Mock Objects vs. \"Inherit & Override\" (osherove.com)") over that class. And that's going to be a big problem. So that might not be a good idea in this case. What about extracting interface? What if each class had a [time provider interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)") that it gets in the constructor? Well, you have the same problem because time is usually used in so many places. [\[02:10\]](https://www.youtube.com/watch?v=jpvaPGdV8ts&t=130s) You're going to have to inject time into so many classes, it becomes very very hard to read and maintain. Although those approaches would work, I don't think they're the best approaches in this case when we have a cross cutting concern like time. So in that kind of case, what I would do is I would actually create a time provider class, an abstraction over the current time. This is an example of what it might look like. and it can give me the current date. So I would have the current date and time. [\[02:43\]](https://www.youtube.com/watch?v=jpvaPGdV8ts&t=163s) So everyone in the production code would have to use this class. So that means that I'm changing the way people work with time and I do [code reviews](https://osherove.com/blog/2007/3/13/test-reviews-vs-code-reviews-some-helpful-tips.html "Test Reviews Vs. Code Reviews - Some Helpful Tips (osherove.com)") to make sure that nobody uses date directly. But instead I want them to always use time provider which is part of the production code. But the nice thing about time provider is that I can have methods that say I want you to force the current the current time and then at the end of my test I can reset so that it sets the date to null and then it will use the current date [\[03:14\]](https://www.youtube.com/watch?v=jpvaPGdV8ts&t=194s) When someone uses it. So this is like almost like a very way a simple singleton approach to to to having time. But this abstraction actually makes our test very readable. At the beginning of our test we force the time to be something. At the end of our test we reset the time. We can even have an after method like a [tear down](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_171 "Setting up and tearing down (The Art of Unit Testing, 3rd ed., ch. 9)") method in [JUnit](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)") that will reset the time automatically for all the tests. So we don't have to worry about it. And this is the case where I said that sometimes before and after methods make sense when you want to reset static stuff. [\[03:47\]](https://www.youtube.com/watch?v=jpvaPGdV8ts&t=227s) So this is an example of something that is static because we don't want to inject the time into all the instances of our of our objects. >> Yeah. So this is a good way to simulate dates. For example, you can say I want this component to to give a notification after 14 days. Then you can basically get the time provider to change the current date. Now another thing that we can do is if we if we have things that keep for example timers or time based things that change every second. [\[04:20\]](https://www.youtube.com/watch?v=jpvaPGdV8ts&t=260s) One of the ways that that we can do it is we can we can make this a bit more interesting by saying that we can get events from the time provider for example on every second that's passing and then we can trigger those events and say I want you to trigger as if 10 seconds just passed etc. So if we have eventbased objects that are listening to the current time based on the thread or something, we can instead change it directly over here. So we don't have to wait all that time. Either way, the time provider is a good abstraction in terms of design because it really removes the time away from your application and it's also good for the tests. [\[04:58\]](https://www.youtube.com/watch?v=jpvaPGdV8ts&t=298s) So what I want you to do is I want you to solve from the timebased problem onwards using a time provider. However, one of the things we'll have to do is to also get the machine name. The machine name, it could be crosscutting or it wouldn't. Usually machine name you don't get in all all in all the all the places. So machine name would be a good candidate for extract and override. So in the next scenario, you will need to [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") both the machine name and the time. [\[05:28\]](https://www.youtube.com/watch?v=jpvaPGdV8ts&t=328s) So you would have a combination of time provider and extract and override. they want you to to use both of them together. Okay. And after that, you can continue to future instances and you'll see that extract and override works very well for future instances as well. ## Related - [Cross-cutting concerns injection](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec5) · The Art of Unit Testing, 2nd ed., ch. 7 The 2nd edition's section on cross-cutting concerns injection, the static time provider approach used for time here. - [Stubbing out time with parameter injection](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_64) · The Art of Unit Testing, 3rd ed., ch. 3 The 3rd edition's section on stubbing out time with parameter injection, an alternative way to control the clock. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Extracting a common interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74), ch. 3 - [Setting up and tearing down](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_171), ch. 9 - [The xUnit frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39), ch. 2 #### The Art of Unit Testing, 2nd ed. - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 - [Mapping out tests based on speed and type](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec2), ch. 7 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 #### osherove.com - [Mock Objects vs. "Inherit & Override"](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html) - [Test Reviews Vs. Code Reviews - Some Helpful Tips](https://osherove.com/blog/2007/3/13/test-reviews-vs-code-reviews-some-helpful-tips.html) [Previous lesson Extract And Override Refactoring](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/extract-and-override-refactoring/) [Next lesson Faking Futures](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/faking-futures/) --- title: "Faking Futures" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/faking-futures.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/faking-futures/" tags: [] author: "Roy Osherove" description: "Lesson 16 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 2:41. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Faking Futures 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 3 Lesson 16 of 21 Duration: 2:41 [Watch on YouTube](https://www.youtube.com/watch?v=A5k38-k__ng) How do you deal with objects being creating directly inside [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)")? We can refactor that! ## In this lesson Roy Osherove discusses an exercise with a login manager that creates a new slow logger, where the test has to prove that the logger's write method is called. He compares extracting a protected method that returns the slow logger, which needs a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") subclass of it, with extracting the whole call into a protected method, which he usually prefers as simpler. ## Transcript 376 words [\[00:03\]](https://www.youtube.com/watch?v=A5k38-k__ng&t=3s) So this is let's talk for a second about the requirement about login manager with future. Now login manager with future you you have a call to new slow logger and the requirement is that you prove that it calls the new slow logger with the method write because this is [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10 "Working with legacy code (The Art of Unit Testing, 2nd ed., ch. 10)"). Now we have two choices when it comes to new. We can either refactor just this part of the call or we can refactor the whole call. [\[00:34\]](https://www.youtube.com/watch?v=A5k38-k__ng&t=34s) If we refactor just the call to slow logger to create the new one we set a method called get slow logger and make it protected. What happens now? We have to return something that looks like a slow logger. In our test, we'd have to create a class that inherits from slow logger, overrides whatever is needed, and then returns that. That's possible, but that's more complicated. We also will inherit anything from slow logger that we don't override. [\[01:04\]](https://www.youtube.com/watch?v=A5k38-k__ng&t=64s) That could mean that maybe it uses something underneath we don't control. So, it's more complicated to do this than to say protected void. or sorry let's undo this whole thing and say extract this whole line say call new logger make that protect it and make this a variable [\[01:40\]](https://www.youtube.com/watch?v=A5k38-k__ng&t=100s) So here we might say text like this. Now, this is very much like what we did before with static logger. It's a much simpler way to check that something was called. So, we can either choose to fake one level below and return the object or we can choose to just call the object in the [simplest way possible](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") and prove that that happened. I usually choose this way [\[02:11\]](https://www.youtube.com/watch?v=A5k38-k__ng&t=131s) Rather than return a slow log or other unless I really have no choice and I only have no choice when I need a [mock object](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") to be called and I have no way to inject the mock object. For example, if I need to check that not a static logger was called but that a new slow logger was called. Right? This is the only way I either have to do this or I have to return an instance. And this this is actually the the simplest way that I know how to do it. ## Related - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5) · The Art of Unit Testing, 2nd ed., ch. 3 The 2nd edition's section on variations on refactoring techniques, comparing extract-and-override choices like these two. - [Issues in breaking dependencies for unit testing](https://osherove.com/blog/2005/8/23/issues-in-breaking-dependencies-for-unit-testing.html) · osherove.com Roy's post on ways to break dependencies on an existing class in legacy code, like the newed-up slow logger. - [Tips for Testable code and for testing legacy code](https://osherove.com/blog/2007/6/10/tips-for-testable-code-and-for-testing-legacy-code.html) · osherove.com Roy's consulting notes on testing a hard-to-test method in legacy code, using refactorings like extract and override. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 #### The Art of Unit Testing, 2nd ed. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10), ch. 10 #### osherove.com - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) [Previous lesson Faking Time](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/faking-time/) [Next lesson Unconstrained Isolation Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/unconstrained-isolation-frameworks/) --- title: "Unconstrained Isolation Frameworks" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/unconstrained-isolation-frameworks.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/unconstrained-isolation-frameworks/" tags: [] author: "Roy Osherove" description: "Lesson 17 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 9:50. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Unconstrained Isolation Frameworks 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 3 Lesson 17 of 21 Duration: 9:50 [Watch on YouTube](https://www.youtube.com/watch?v=OklXvglbBxA) In this talk we learn what frameworks such as Powermock and [JMockit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") have to offer, both in terms of APIs and in terms of test [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)") and maintinability. ## In this lesson Roy Osherove shows the static logger test written with [PowerMock](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)"), Mockito and [JUnit](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)"), using the run with annotation with the PowerMock runner, an annotation that loads the static logger class differently, and verify static before each verified call. He then shows the same tests in JMockit, which has to be loaded before JUnit and uses [non-strict](https://osherove.com/blog/2013/11/23/fifteen-things-i-look-for-in-an-isolation-framework.html "Fifteen things I look for in an Isolation framework (osherove.com)") expectations and verifications blocks. He does not usually recommend JMockit because calls are repeated twice and tests get wordy, and suggests starting the exercises with PowerMock. ## Transcript 1,458 words [\[00:02\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=2s) Let's talk about [unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)"). Up until now, what we did was we used [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") or using static class to to abstract away things that like time. Now let's talk about what happens if we cannot change our code using either refactoring or we don't own the code or we're afraid to change it. That's where tools like PowerMock come into play. So, PowerMock is an added extension that you can use with [JUnit](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)"), with Mockito, with TestNG. [\[00:34\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=34s) It's basically an addition that works with most other things. When you download it, you have many variations. We are going to use the variation that is the PowerMock with Mockito and JUnit. It has different variations for the frameworks that you would use. For example, if you're using EasyMock, you would use a different a different download. This is the test, the classic test of [string calculator](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)") that has to call a logger. [\[01:06\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=66s) Only this time it's a static logger without the need to refactor. So the first thing we notice is that we have two special annotations at the top of the test. The first is run with which is part of JUnit and it tells us to use a different testr runner and here we would use PowerMock runner class. Now that's important because PowerMock under underneath will do a lot of magic quote unquote to [\[01:36\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=96s) To basically manipulate bytes and class loaders so that it can inject behavior into any method it wants. And then we have to let PowerMock know that in this test we want to load a special version of static logger class. This basically loads the class differently in memory and what happens later is that in the test we have to [\[02:07\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=127s) [Fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") the static methods of static logger. So this is just loading it differently. This one tells PowerMock or in this case it's called PowerMockito because it's special extension for Mockito to fake the static methods of static logger. And this is all we have to do really from this moment on the static methods will not do anything but we can also verify on them. So we do this we mock all the statics but we actually I'm just saying we're faking them. [\[02:37\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=157s) But we use one of them as a mock object. So to verify a static method we have to do two actions with PowerMock. We have to say that the next call is going to be a verification on a static method and then we actually do the call but we can use the matchers from ok from from JUnit and from Mockito. So in this case we're saying any string. So again this is basically our the first line of verify static tells PowerMockito that the next invocation on static logger is actually not real and it's an expectation. [\[03:20\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=200s) That's why you need to do this for every call if you're going to verify multiple calls which is already a bad idea. Why do you know why is it a bad idea to verify multiple calls in a single test? more than one. >> It's testing more than one thing. Exactly. So you wouldn't need to have more than these two calls if you're verifying a static method because that's a single [end result](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)"). But either way, you have to remember to say verify static and only then to do the call. [\[03:52\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=232s) So that's the way that PowerMock works. And it's once you get used to it, it's actually pretty easy to do things. Here's how it would work with the JMockit. JMockit is a separate framework. You can write tests with it. It can run on top of the JUnit testr runner. But when you use the class library, you have to put the jar file in front of or before JUnit. So JMockit has to be loaded into memory before JUnit is loaded into memory. [\[04:27\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=267s) That makes JMockit also load JUnit in a completely different way. So it can trace everything that's that gets called. Here is the same test with JMockit and you'll see that it looks completely different. First of all, we have two special sections in the test. The [arrange part](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "The Arrange-Act-Assert pattern (The Art of Unit Testing, 3rd ed., ch. 2)") looks like new [non-strict](https://osherove.com/blog/2013/11/23/fifteen-things-i-look-for-in-an-isolation-framework.html "Fifteen things I look for in an Isolation framework (osherove.com)") expectations. That's a special class that's part of JMockit. And in the non-strict expectations, we set up how we want fake things to behave. [\[05:00\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=300s) And in the bottom we have verifications which are basically our verifications or asserts. So let's focus on one of them. When we look at the non-strict expectations when we have two types of expectations we have strict we have non-strict. We want the non-strict. Always remember that right? Because if we you we would have used the strict version of those we would say new new expectations. That's how it was called. And then anything that was not expected would break our test [\[05:33\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=333s) Which is not what we want. We want that any number of things might be called. We just verify later what was called. However, you still have to tell JMockit what's going to happen. So even in the non-strict expectations even if I just want to make sure the static logger right was called I still have to say to JMockit to how do I call this interlace or what do you call when you go through a piece of code and you trace through it. [\[06:10\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=370s) I don't remember the the exact name but basically to use static logger and to start verifying it in memory without this call I cannot verify on static logger.write Right? So I would have to make this call for each method that I might verify on. That's important because it means that I now have to repeat each method twice, which is not a good thing. Then in my verification, sorry. And I and then I can use a special constant called any string, which looks like any string from Okto, but it's not. [\[06:43\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=403s) It's not a method if you notice. If I wanted to use matchers, like I don't want to have a hard-coded string to be expected here. Now when I want to verify I use new verifications and then I basically call static logger write and then I can use another example of matcher with substring of got one. So again I have to repeat the call twice when I use JMockit which is something that I specifically don't like and it's the reason why I don't usually recommend JMockit too much. [\[07:15\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=435s) Although the syntax can grow on you, I don't like it because you have to your test becomes very wordy and you have to add a new line for each line you verify. Are there any questions so far? Okay. Let me see if I have a good demo for you guys. This is Java drills. This is Java demos. [\[07:46\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=466s) I might have a slightly more interesting demos. Let's see. Let's see. Let's see. Unconstraight. Okay. So, here are the same tests again with J with the PowerMock. But what I wanted to show you specifically was the one with the JMockit. I wanted to show you how wordy it gets [\[08:18\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=498s) When you want to have something that has one [stub](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") and one mock object. So in this case, the test is logger throws call static web service. So I have non-strict expectations and then then I say something special static logger I define it and then I define these properties on it static logger.write with anything and then I say result equals new out of memory error. So this is how you would specify that something in JMockit would return an error. [\[08:49\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=529s) You would say result after the call. There is another syntax called mockup which is even more complicated so I'm not even showing it here. And then for static web service you have to again do a definition and say notify is going to be called at some point and then you verify on static web service. Just look at how long the test becomes. So that's for example how you could do that and make something throw an error in JMockit. But that's also the reason that I don't like to use it too much. [\[09:20\]](https://www.youtube.com/watch?v=OklXvglbBxA&t=560s) It's very very worthy and it also repeats itself a lot of a lot of times. So if there aren't any questions, what I want you to do is I want you to repeat the exercises from the static logger from the beginning of making calls to the static logger. The first exercise of [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") and try to do them all with PowerMock or with JMockit whichever one you choose. I would recommend to start with PowerMock because I think it's more maintainable framework. ## Related - [Constrained and unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1) · The Art of Unit Testing, 2nd ed., ch. 6 The 2nd edition's section on constrained and unconstrained frameworks, the category PowerMock and JMockit belong to. - [Isolation framework design antipatterns](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec4) · The Art of Unit Testing, 2nd ed., ch. 6 Section on isolation framework design antipatterns, relevant to the wordy, repeated JMockit syntax shown here. - [Values of good isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec2) · The Art of Unit Testing, 2nd ed., ch. 6 Section on the values of good isolation frameworks, a yardstick for comparing PowerMock and JMockit. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [The xUnit frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39), ch. 2 - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19), ch. 1 - [The Arrange-Act-Assert pattern](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2), ch. 2 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 #### The Art of Unit Testing, 2nd ed. - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 #### osherove.com - [Fifteen things I look for in an Isolation framework](https://osherove.com/blog/2013/11/23/fifteen-things-i-look-for-in-an-isolation-framework.html) - [TDD Kata 1 - String Calculator](https://osherove.com/tdd-kata-1) [Previous lesson Faking Futures](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/faking-futures/) [Next lesson Throw Errors with Powermock](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/throw-errors-with-powermock/) --- title: "Throw Errors with Powermock" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/throw-errors-with-powermock.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/throw-errors-with-powermock/" tags: [] author: "Roy Osherove" description: "Lesson 18 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 1:21. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Throw Errors with Powermock 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 3 Lesson 18 of 21 Duration: 1:21 [Watch on YouTube](https://www.youtube.com/watch?v=1T04JPawUiU) A quick demo showing how to make static methods throw errors with Powermock. ## In this lesson Roy Osherove shows how to make the write method of a static logger throw an exception with [PowerMock](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)"): after mock static, doThrow with an out of memory exception is set on the static logger class, and the next call to the static logger is the one that throws. He notes that this API is not obvious at first and that a matcher such as any string tells the reader more. ## Transcript 196 words [\[00:03\]](https://www.youtube.com/watch?v=1T04JPawUiU&t=3s) I didn't show how to throw how to throw expect exceptions with the [PowerMock](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)"). So this is a very simple demo for that. Now it looks weird the first time you do it but if I wanted the write method of static logger to throw an exception I would have to do this. I do the mock static just like before. I say do throw new out of memory exception when then I say static logger.class class not the method that's the limitations of the API and then the next call to the static logger is the thing that will throw the exception [\[00:42\]](https://www.youtube.com/watch?v=1T04JPawUiU&t=42s) Okay so it's better to use a matcher like any string etc so that the reader will know a bit more that this is a thing or maybe it's better to do something like this maybe that's a bit more readable I'm not sure Maybe this way. Either way, I wanted to show that this thing is somehow connected to the things above. Okay? So, it's not very obvious when you just start to use the API. [\[01:14\]](https://www.youtube.com/watch?v=1T04JPawUiU&t=74s) So, you should know how to do that. How to simulate behavior from something static. Okay? ## Related - [Simulating fake values](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 5 The 2nd edition's section on simulating fake values with a framework, including making a fake throw an exception. - [Faking static methods in Moq, FakeItEasy and NSubstitute might be closer than imagined](https://osherove.com/blog/2012/7/8/faking-static-methods-in-moq-fakeiteasy-and-nsubstitute-migh.html) · osherove.com Roy's post on faking static methods with constrained .NET frameworks, the same static-faking problem. ### Also linked in this lesson #### The Art of Unit Testing, 2nd ed. - [Constrained and unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1), ch. 6 [Previous lesson Unconstrained Isolation Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/unconstrained-isolation-frameworks/) [Next lesson Discussion About Pros and Cons of Unconstrained Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/discussion-about-pros-and-cons-of-unconstrained-frameworks/) --- title: "Discussion About Pros and Cons of Unconstrained Frameworks" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/discussion-about-pros-and-cons-of-unconstrained-frameworks.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/discussion-about-pros-and-cons-of-unconstrained-frameworks/" tags: [] author: "Roy Osherove" description: "Lesson 19 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 2:14. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Discussion About Pros and Cons of Unconstrained Frameworks 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 3 Lesson 19 of 21 Duration: 2:14 [Watch on YouTube](https://www.youtube.com/watch?v=61oUXV-rrrU) Is it really easier and simpler to write tests for [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10 "Working with legacy code (The Art of Unit Testing, 2nd ed., ch. 10)") using [unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") in Java? Is it easier and simpler to refactor the code? Let\`s talk about it. ## In this lesson After the exercises Roy Osherove asks how [unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") felt, concludes that they were much more complicated than refactoring, and explains that an API for faking private and static methods, constructors and other [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") features has to be as complex as legacy code. He says tools like PowerMock and JMockit let you test code without changing it but give up the [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)") and [maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)") that refactoring brings, so they should be used like a nuclear weapon. ## Transcript 348 words [\[00:05\]](https://www.youtube.com/watch?v=61oUXV-rrrU&t=5s) Okay, I want you to stop. Okay. How was that experience of working with [unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)")? Did they unconstrain you? Did they complicate or simplify? Complicate. They were much more complicated than refactoring. And one of the things I wanted you to realize is that the fact that some frameworks can actually do these things doesn't actually mean that they help us. So I would say that most of the time, especially in Java with the current frameworks that we have, it's not always a good idea to use something like PowerMock or JMockit. [\[00:44\]](https://www.youtube.com/watch?v=61oUXV-rrrU&t=44s) The reason is because the APIs that try to solve the problem of [legacy code](https://osherove.com/blog/2013/2/8/when-i-fight-with-legacy-code.html "When I fight with legacy code (osherove.com)") have to be as complex as legacy code because legacy code has a lot of features. For example, private methods, you need to have an API to [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") a private method. Static methods, you need to have an API for that. Private static methods, you need to have an API for that as well. What about constructors? You need to have an API for faking a constructor. future objects, static constructors, [\[01:16\]](https://www.youtube.com/watch?v=61oUXV-rrrU&t=76s) Okay, collections, arrays, all the things that it tries because they can handle so many things. They the API also has to handle all these things that makes the API almost like a dictionary. You have to look things up all the time and the code can become pretty horrible. When we were using [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)"), our code and our tests were so simple and once you got it working, it was very easy to write new new tests. Now, if you learn the API for things like PowerMock, you will be able to test these things without changing them, but you're not getting any benefit from it. [\[01:54\]](https://www.youtube.com/watch?v=61oUXV-rrrU&t=114s) You're not getting the benefit of refactoring your code to be more readable and more maintainable. You might actually be also making your tests less readable and less So there is a big trade-off here. Only use these things like a nuclear weapon and realize that it's going to hurt the environment just as much as it helps you. ## Related - [Is Typemock too powerful? Will it kill design for testability?](https://osherove.com/blog/2008/1/17/is-typemock-too-powerful-will-it-kill-design-for-testability.html) · osherove.com Roy asks whether an unconstrained framework kills design for testability, the debate in this discussion. - [Pros and cons of designing for testability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 11 The 2nd edition's section on pros and cons of designing for testability versus faking legacy code as is. - [Alternatives to designing for testability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec4) · The Art of Unit Testing, 2nd ed., ch. 11 Section on alternatives to designing for testability, where unconstrained frameworks are one option. - [Unreadable test code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5) · The Art of Unit Testing, 3rd ed., ch. 5 The 3rd edition's section on unreadable test code from isolation frameworks, the complexity noted here. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 - [Maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8), ch. 8 #### The Art of Unit Testing, 2nd ed. - [Constrained and unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1), ch. 6 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10), ch. 10 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 #### osherove.com - [When I fight with legacy code](https://osherove.com/blog/2013/2/8/when-i-fight-with-legacy-code.html) [Previous lesson Throw Errors with Powermock](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/throw-errors-with-powermock/) [Next lesson Continuous Delivery](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/continuous-delivery/) --- title: "Continuous Delivery" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/continuous-delivery.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/continuous-delivery/" tags: [] author: "Roy Osherove" description: "Lesson 20 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 42:33. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Continuous Delivery 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 3 Lesson 20 of 21 Duration: 42:33 [Watch on YouTube](https://www.youtube.com/watch?v=WPSSx8RcvhU) In this talk we step back and look at our [build process](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec1 "Automated builds running automated tests (The Art of Unit Testing, 2nd ed., ch. 7)"), and where the tests fit in it. We also talk about some best practices during builds. ## In this lesson Drawing on his book in progress [Beautiful Build](https://osherove.com/videos/2013/5/17/video-beautiful-builds.html "Video: Beautiful Builds (osherove.com)"), Roy Osherove calls releases the [best form of compilation](https://pipelinedriven.org/article/2014/3/2/release-compilation "Release Compilation (pipelinedriven.org)") and separates [build controllers](https://osherove.com/blog/2010/1/14/the-difference-between-continuous-integration-tools-and-auto.html "The difference between continuous Integration tools and automated build tools (osherove.com)") such as TeamCity or Jenkins, build agents and build scripts by what each should know. He recommends starting with a [shipping skeleton](https://pipelinedriven.org/article/2014/3/2/pattern-shipping-skeleton "Pattern: Shipping Skeleton (pipelinedriven.org)"), a hello world application that goes through the whole release chain, and covers cumulative builds sharing artifacts, snapshot dependencies, [build script injection](https://pipelinedriven.org/article/2014/3/2/pattern-script-injection "Pattern: Script Injection (pipelinedriven.org)") and parameterized FinalBuilder scripts. He also discusses the [bus factor](https://www.5whys.com/articles/the-bus-factor-why-your-best-developer-is-your-biggest-probl.html "The Bus Factor - Why your ‘best’ developer is your biggest problem (5whys.com)"), build waves that let developers resume coding once [CI passes](https://pipelinedriven.org/article/2015/5/15/time-to-main-measuring-continuous-integration "Time to Main - Measuring Continuous Integration (pipelinedriven.org)"), and why breaking the build should not be discouraged. ## Transcript 7,230 words [\[00:02\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2s) I want to finish up with the the big picture of of the [build process](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec1 "Automated builds running automated tests (The Art of Unit Testing, 2nd ed., ch. 7)"). I'm actually writing a book called [Beautiful Build](https://osherove.com/videos/2013/5/17/video-beautiful-builds.html "Video: Beautiful Builds (osherove.com)") right now and this is this is part of that book and I want to talk to you about how I approach the delivery process. So the first thing I want to talk about is the idea of compilation. Can you imagine compiling your code once a week? [\[00:34\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=34s) You can write code the whole week, but you only get to compile it once a week. Can you imagine what life would be like? Pretty great, right? Life would be hell on that day, but on the other days, it's just going to be one big party because you you know you're going to fail. So we have compilers to help us continuously to know that the code we write actually compiles actually [\[01:05\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=65s) Actually actually fits the compiler that requires it. So we can do that continuously. What about tests? [Unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)"). Can you imagine running tests only once a week? You could do that. A lot of people actually do and that creates a lot of problems. But a lot of people have stopped doing running tests once a week or once every two weeks. [\[01:36\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=96s) A lot of them actually run the test continuously as well. So they have the test in a in a [continuous integration](https://pipelinedriven.org/article/2015/5/15/time-to-main-measuring-continuous-integration "Time to Main - Measuring Continuous Integration (pipelinedriven.org)") cycle. Things like what are you using? Jenkins. Things like TeamCity and then every time they check in the code the unit tests run and they give a quick very quick feedback and you can also run the test locally on your machine and get quick feedback and that's nice because you know that your code not only compiles but it also matches the reality of the requirements or at least the requirements that you know. [\[02:16\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=136s) Now let's look at the next level. What about can you imagine releasing every two months? Of course you can. That's what we do. Can you imagine releasing every two weeks? Some people do that. Can you imagine releasing every day? Not many people do that. What about releasing many times a day? That's what we're talking about. Why do we want to release multiple times a day? continuously because whenever we release we find out new problems that we didn't think about. [\[02:50\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=170s) For example, does our code actually match the system where it's supposed to be deployed? How long does it take you to know when you wrote a piece of code that it actually works on the end machine where it's supposed to run? For example, on the actual computer of the user or if it's a website that it runs with the actual browser that the user is using. Not only that, how do you know that the user who's using it is actually using what they want? Even if it works perfectly with the browser, is it what they actually wanted? [\[03:21\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=201s) And releases give us the ability to get feedback from the users to know we are on the right track or not. Without frequent releases, we don't have feedback that our code matches the reality of what's actually requested. So in a way, releases are the [best form of compilation](https://pipelinedriven.org/article/2014/3/2/release-compilation "Release Compilation (pipelinedriven.org)") for our code. We have compilers to make sure that it compiles for the computer. We have unit test to make sure it compiles for the requirements we think we have. We have release to make sure that our code can actually be released. [\[03:51\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=231s) So release is actually the best test for our code. To deploy as much as possible is to test our code as much as possible against what we think the reality is and what it actually is. If we release every two months, we might be working two months on the wrong thing. Or if we release every two months or we release at the end of the year, we might find out at the end of the year that the requirements from the hardware or the security or anything else like that were that we assumed were true were not and now we have to go back and maybe change some of the product or our estimation or the deployment and everything based on the end result where we're supposed to deploy. [\[04:36\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=276s) So deploying is actually a compilation of our code in the best way possible. So what I want us to do is to think about it in the culture of continuous release as continuous compilation. So my recommendations that we're going to talk about here is that we going to have we're going to talk about build automation. And I know that you already have some of it, but I want to talk about the vision of how build automation could work and how to solve common problems when we we do automated builds and how to choose good tools for continuous integration and automated builds. [\[05:18\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=318s) First I want to talk about the three levels of things that happen during the build cycle. We have at the lowest level we have build scripts that those are the scripts like Ant or batch files or script files like shell files shell scripts that are the things that actually do all the hard work. On the top level, we have servers that manage builds like TeamCity, like Jenkins. [\[05:50\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=350s) Those are the things that are supposed to trigger automated builds whenever we check in or every hour. And on the middle, we have the things that execute the commands from the high level. we have [build agents](https://osherove.com/blog/2010/1/14/the-difference-between-continuous-integration-tools-and-auto.html "The difference between continuous Integration tools and automated build tools (osherove.com)") or sometimes we don't have the high level, we just have the mid level of a service that automatically runs or we have a cron job that that that waits for something to happen and then imports something. But they all execute at the end the build script. [\[06:21\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=381s) Now why is it important to know about the build actors? Because the build actors should have different types of information. And a lot of times when we do automated builds, we share the information between all these actors when we actually shouldn't. Each actor should have different types of information and that actually makes our builds more maintainable. As a simple example, the build script shouldn't know the password to the FTP server when deploying. Who should know that? The high level, the build controllers. [\[06:53\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=413s) TeamCity should know the password because that's a systemwide knowledge that keeps changing. We don't want that in source control. On the other hand, the team or Jenkins doesn't need to know the exact places in our code path in the source control where the unit tests are or where the zip files are or where the jar files should be. It should just know the root location because if it knows about the structure of our code, the structure of our code can change from version to version and so we would need to keep changing the high level controllers and the configuration. [\[07:30\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=450s) Who should know about the structure of our code? The build script because the build script is part of source control. So it's versioned. So if you get the build script from three months ago, it will match exactly the structure of the code from three months ago. If you try to run and the knowledge is up there in the build controller and you try to run a build from three months ago, it might not work because it assumes a specific code structure if it thinks it knows it and it's going to be wrong. Another example, [\[08:01\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=481s) I just had this at another project is that we had the we had a TeamCity instance that we had to reinstall and everyone was freaking out because they were afraid that all the build scripts, all the build actions and the build steps in TeamCity will be deleted. We'll have to reconfigure them and they were not versioned. It's in a database, but we have to restore a database and all that stuff. That's complicated. But we didn't have all that problem, all those problems because TeamCity was just a very simple trigger to invoke a script file that was in source control. [\[08:37\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=517s) So to reinstall it and to put one simple step that invokes a build a build script took about 10 minutes because we were not afraid because all the knowledge of what to do was mostly here. Okay, so that's how I think about them. I forgot to show you this nice image. So the the build controllers, they control the environment. They know about where are the servers to deploy to. [\[09:08\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=548s) They don't know the password. They know the passwords to the place to to various servers. They know which route from source control to take. The mid-level they just execute. they have a command from the build controller to say run me the script that's located in this piece of source. So they get the source and they get triggered and then they execute this and this script doesn't know anything. It just executes. It doesn't know where it came from. It doesn't know where it's coming to. It's relative. It doesn't know the location. [\[09:40\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=580s) It can run in any computer. It should be in its own little world just running and running. Poor little cat. Now before we understand the build we have to understand the difference between continuous integration and automated builds. Continuous integration is when to trigger the builds. That's the build controllers. Automated builds are the build scripts. Those are the scripts that determine what should happen. So I should have a just trigger for example when someone checks in. [\[10:11\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=611s) So a continuous integration will trigger an automated build. That's how you think about it. Now I want to talk about some patterns specifically things that keep happening. I've been working with builds for more than 15 years and I've had all of these problems and that's why I'm actually writing that book. So I want to start with with the simplest force is that we want to start having feedback as quickly as possible. [\[10:43\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=643s) But to set up an automated build is very very difficult because our project is already running. We have too many things going on and so we're kind of screwed. And this is where I would say that we should start with a [shipping skeleton](https://www.youtube.com/watch?v=8jeIwGzuqJ8 "Start by Shipping : Shipping Skeleton (YouTube)"). A shipping skeleton is hopefully you started as the first iteration of your project. Now if you start your project on an enforced iteration, you start by releasing the product and then you have a spine, you have a chain of builds that will trigger from continuous integration all the way to release. [\[11:22\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=682s) If you can automate that on the first iteration that you have in the first couple of weeks, then you have a spine to work on and then just add more and more features. So the skeleton is basically a simple hello world application. It doesn't do anything. It just says hello world as far as we're concerned either on a web page or a console or something something that we can ship and then show on the end machine of a customer or some or someone and then we take this little piece of code three lines of code and then we say okay let's make this go through all the release cycle that we're going to have during this project. [\[11:57\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=717s) That means it's going to go through running unit test which don't exist yet. We'll go through running [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)") that don't exist yet. We'll go through deployment to test, deployment to staging, deployment to release, and I'll show you the structure of that in a second. But the nice thing about having a shipping skeleton is that you don't focus on the functionality first. You focus on shipping first. And that means that you might need to get the hardware to deploy to. If you don't have a production server, you should have one on the first iteration. [\[12:30\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=750s) If you have to wait for the production server to to happen at the end of the project, what's going to happen is that at the end of the project, especially when you're the most stressed, you're going to have to stop and start configuring the server and then realize all the constraints that you had that you didn't think about when you started building your product. But if you get all that out of the way on the first iteration, what's going to happen is that you're going to figure out all those problems in the beginning and you're going to solve all that crap in the beginning. And what's going to happen is that you're going to fix it and you're just going to forget about it. [\[13:04\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=784s) From that moment on, you're always going to deploy and deploy and deploy. So what happens in the first iteration, it's all being recorded. You should know that. So if you hear in the recording, okay, so we want to have a shipping skeleton. And what's going to happen is that okay what is the simplest build chain that I could think of well we have in terms of hardware or virtual machines what I like to have is that to have first we have need a build machine we need a server or something that runs a continuous integration server could be Jenkins could be TeamCity could be something else I personally like TeamCity because the the I think it's much more productive and I don't have to edit XML files and I hate editing XML files And one thing I know about Java, [\[13:56\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=836s) Lots of XML files. It's just I don't know. It's the thing. It's like you program XML and sometimes you do a little Java and XML is just horrible for maintainability by people because it's case sensitive and it's space sensitive and it's a lot it's just very sensitive and that means that it's not very humanly friendly. So I like to avoid XML as much as possible. So I will have TeamCity and TeamCity also has a build agent built in. [\[14:26\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=866s) That means that already I can start running my build with a single agent for free. I get two more agents if I want to and I can install them on two more different build machines. But I would also want a test environment machine something to deploy to to test so that either testers or anyone else can go and see demos of the product in its latest version. I would want a staging machine as well as a production machine. A staging machine is a production is a production machine which sits next to me and looks exactly like a production machine. [\[14:59\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=899s) So it has all the constraints in terms of security, active directory or anything like that. It has the same exact constraints as production. For example, if I if I have to deploy to production via FTP, I also have to deploy to staging via FTP. Okay, that's important because by being able to deploy to staging, I'm actually testing my deploy script and then I know that if I can deploy to staging, I can deploy to production. [\[15:29\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=929s) You don't want to deploy to production continuously five times a day. You want to deploy to production by a click of a button maybe, but not automatically. That's the last place. But everything else can happen automatically. So we want to test our build scripts by having a staging machine. Now I've done this with the Amazon EC2 and had six different virtual machines. In the current project we're working on we have seven build agents and 20 build machines. And it's a wonderful thing because we have many people checking in when we keep seeing the statuses of the builds whether they broke something or not. [\[16:06\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=966s) And we have automated configuration and automated deployments. In terms of the build configurations, the build configurations are the confi are basically the stages that my code goes through. The first one is continuous integration. That's the one that should run the fastest. Usually it runs unit tests and it just compiles the code. That shouldn't take more than a couple of minutes. It gets the source control and it runs the unit tests. [\[16:39\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=999s) Then I might have if I already have integration test I might create a slow build configuration. Now I usually call it nightly but as far as I'm concerned this can run multiple times a day as well. If nobody checks in what the hell the CPU is not being used I might as well run the slow builds as well. And one thing I like to do is to actually trigger the slow build automatically once the continuous integration build runs and passes. The third thing that I do is that I have a deploy. At the minimum, I need a deploy to test if I don't have staging yet. [\[17:13\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1033s) But I need somewhere to show a demo. I don't want to show it on the developer machine. Now, the the problem with test is that the test machine is usually not clean. It might have debugging tools or even compilers, IDEs. So, it's not as good for demos because what you would really want to show is a demo on something that looks as close as possible to the customer machine because you want to find out as many problems as as pos as you can possibly get [\[17:44\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1064s) Another build configuration to deploy to staging and deploy to production. Now, what usually happens is that the same deploy script for staging and production is being used only with different parameters between those last two configurations. But deploy to test usually is a separate is a different deploy script because the because the requirements for deploying to test are usually less severe than the deploys to staging and production. That would be so four out of these would be the ones I would start with. [\[18:18\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1098s) The the one I would not necessarily start with is the slow build because I might not have integration tests just yet. And then as time goes by, I add more features to the build. Yes. >> Where would you run the demos then? >> Where would I run the demos? If I if I have all of these, I would run them on production if I could. In one of the projects that I did, which was I'm not going to say, but in one of the projects that I did, we had a production server running. [\[18:49\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1129s) It just wasn't live. The DNS was not set up yet. But we could go to the IP of the machine and show a demo on the production machine, which was the best demo because it was publicly available. We could send the IP to our customers and they would see it to our internal customers. They would see it. They would just need to enter a password to be able to see the website. So for us that was perfect because if I can if I can go the whole way and deploy a new feature and say, "Okay, give me five minutes." And it took five minutes to go through. [\[19:22\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1162s) Give me five minutes I'll show you and you can just go to the IP and login and you can see the feature that would be best because then I wouldn't have any fear that it works on that machine but doesn't work on that machine so staging is great but production is always better the only time when production wouldn't be better is if people are actually actively working on it and you're going going to screw up their day by deploying a new version maybe delete something or something like that. So deploy to staging is the is hopefully the minimum that you can get. [\[19:52\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1192s) But you know realistically is re in reality you cannot always argue with the facts and the facts are that you might only have a test server. So a test server is good for demos as well as far away from developer machines that that's better for demos. That's kind of the rule. Okay. Closer to production is better for demos because it shows the application in a real situation. How many you have a database? How many databases? >> If I have a database, then I probably would have a test database, a staging database, and a production database. [\[20:27\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1227s) Yeah. And then that would force me to have a deploy script that also merges the databases and scripts. But that would force me to do that, which I would have done anyway. I just start with it when it's simple. And then adding small features to the script is much easier than having the whole thing in the middle of the project doing it all at once. Sometimes there's also a developer server, so you might end up a developer database. So, it really depends. Sometimes each developer has their own database. [\[20:58\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1258s) Sometimes there's a shared database for developers. Either way, you have to be able to script very automatically setting up and removing the databases if you need to. This is what it looks like when I was using TeamCity. Now the the the there's a project that you don't see the name here but but on the left you can see the numbers. The numbers are actually just strings. I put the strings in the names of the of the build configurations so that you can see the flow the order. [\[21:29\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1289s) That's important for a build to be beautiful. I should be able to see the flow of where the code comes in and where the code gets out. So I don't want I want things sorted very very nicely. So and I also gave it numbers of hundreds so that I can fit in other build configurations in the middle if I need to to put them in the middle. So if I if I decide that tomorrow I need between CI and deploy to test. If I decide that I need a a slow build, a nightly build, I just call it 050 [\[22:02\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1322s) And then slow build so that it matches right between the first two. So readability is very important. This is the beginning of a very early project. You can see we only had 13 tests. Now, here's another problem that keeps happening is that when you have a lot of builds, what's going to happen is that you're going to have a [\[22:33\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1353s) You're going to have this problem. The more the build becomes more important, the more you want the build to do. For example, CI would run the unit tests. But if you want to deploy to test, you would want to run the unit test first, right? You would want to make sure it compiles and runs the unit test just like CI did before you deploy. Now obviously if you had a slower build you would want before deploying to test you would want to run CI or you would want to run the unit test and the integration tests and to compile first before doing that. [\[23:10\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1390s) So the situation that happens is that each build becomes slower and slower because they do more and more things. So the sol solution to this is what I call commulative build that each build adds on top of the other build. So instead of having each build do one more thing than the other builds, what we want to do is to use a feature called artifacts so that each build does only one thing. Now artifacts are something that not all continuous integration servers support. [\[23:44\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1424s) I'm not sure if Jenkins supports it or not. It could. I'm not sure. I definitely know that TeamCity uses it. And the the nice thing about it is that if you learn to use it, you can you can have very effective builds. So in this what you see here what I've set up is that I have continuous CI build having doing compilation and running tests and then I publish all the output all the binaries that were compiled and were passing the test. I publish them as artifacts [\[24:15\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1455s) And as I publish them as artifacts, they are available for all the other builds to consume. So I'm actually sharing the binaries to the other builds. That means that the other builds don't have to repeat the same steps. They can just take the binaries that already passed tests and already been compiled and just add one more thing on those binaries. For example, if I had a slow build, I don't need to get things from source control. I don't need to compile and I don't need to run the unit tests. I just get the binaries from the artifacts of the CI and I just run the slow builds. [\[24:50\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1490s) That means that the integration build saves time. It doesn't need to get source control compile and all that stuff. The same for test. Before I run deploy to test, I don't need to do compile and run unit test. I just need to get the artifacts from the CI and just deploy them. So that just takes a few seconds. the same for staging and prod. And there's something even more interesting here. I can I can say that the thing that I deploy to production is the actual thing that was deployed to staging that was deployed to test that was run that was passing the test in CI. [\[25:27\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1527s) The actual binaries, not just a copy that was recompiled, the actual binaries. That's a powerful feature. And one way to make sure that happens is by having what's called a snapshot dependency between the builds. What we have now is artifacts dependencies that the builds take the artifacts from each other. But we can also set what's called a snapshot dependency. So that TeamCity will make sure that if I get the artifacts from this build from deployment of to test to deployment to staging then it will make sure that the snapshot of the code is the same version. [\[26:06\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1566s) So if before I deploy to staging someone committed a new piece of code then test will actually run again before deployment to staging happens. So to make sure that if I if I trigger deploy to production and there's a new version of source code that hasn't been gone through all the steps it will automatically trigger CI deploy to test staging and only then prod will actually happen and that's what I want. I want the same version happening in all the builds. [\[26:36\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1596s) One of the biggest problems that I've had in one of the projects is that we had a lot of teams delivering many modules and the modules had dependencies on one on the other. And what happened is that they they would keep getting the wrong versions of different modules because it was a big project. keep people kept committing things into source control and so the builds were getting were sharing the binaries but the viruses were not updating fast enough. So other builds that were triggered were getting an old version of the binaries and suddenly compilation failures [\[27:10\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1630s) When when all they had to do was to start doing snapshot dependencies and that would have made sure that that could never happen again. So this makes our builds really really fast. from continuous integration to deployment four minutes. That's what you want. That's [continuous delivery](https://pipelinedriven.org/article/continuous-delivery-values "Continuous Delivery Values (pipelinedriven.org)"). Of course, the more tests you have, the slower it gets. But being able to deliver to production even in 30 minutes, that's something that you can be proud of. [\[27:48\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1668s) Another thing that I talked about is what happens with versioning. you want to run a version of your product and deliver something from a month ago. This is where having the scripts in source control and injecting them into the build controller to execute is an important skill. It's important technique. So I call it [build script injection](https://pipelinedriven.org/article/2014/3/2/pattern-script-injection "Pattern: Script Injection (pipelinedriven.org)") and the basic idea is that you take the build script you put it in source control at the root and then when the thing when the CI controller such as TeamCity gets the latest version the agent gets the latest version you just tell it look get latest version and invoke the build file at the root with this name that's all you have to know [\[28:29\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1709s) And so if I wanted to add more features to my build script to my build I just change the build script and check it into source control that gets injected automatically and gets executed by TeamCity or Jenkins or whatever it is that's very powerful because I only make the build based on the current structure of the source. So if the build from three months ago had a different structure of the source and I try to run the build with the source code from three months ago, it will just work because the structure has changed but this the build script has also changed. [\[29:06\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1746s) So the build scripts the code knows how to build itself and the CI controller only triggers the build. That's the difference between the knowledge of the structure or knowledge of the of the systems around it. Another common thing that happens is that you keep having the same script run over and over and you keep creating copies of scripts. You want to deploy to test, you want to deploy to staging, to deploy to production and then you have three different build scripts. [\[29:38\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1778s) What you should have is to try to don't repeat yourself also in build script just like programming. If you could have one script which just accepts parameter for deployment that's a much cleaner way but it only does deploys. So a script should do one thing but it can do the same one thing for different for different locations. So if I want to deploy to staging, if if I need to upload to an FTP and then restart something on a remote server for staging and I need to do the exact same things for production, there is no reason not to do it as a as a script that takes parameters. [\[30:14\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1814s) So I call this pattern fill in the blanks. And this is an example from a built file in a application called FinalBuilder. It actually costs money, but I find that it's very maintainable way because I don't have to deal with XML again. And what's cool about FinalBuilder is that and I I'm not getting any money from them. I'm just a happy customer. What's cool about this is that you can see the structure of the build. You can even put break points. You can debug the build the the build script and it has hundreds of built-in tasks [\[30:49\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1849s) From restarting services to copying things to unzipping whatever you want. It's you it's mostly Windows-based. So that's the only caveat that we have. But one thing that all script scripts should be allowed to do is to have these parameters right here. You see text to find and test page. This is a script that's called you see the top check site. I call the scripts from many different deploys. [\[31:19\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1879s) For example, after I deploy to test, I call this script. I say tell me that the site that I just deployed actually is actually working. Give me a sanity test. So it goes to the site and it has a loop and then it looks for a specific either 404 or whatever it is and it downloads the file and tells you and it breaks the build if the deploy didn't work. But then I use the same file for staging and and production as well. I just change the variables either as an environment variable or as a command line variable that allows me to reuse it. [\[31:53\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1913s) So if tomorrow checking a page changes or I need to change how I check it for example test a different page I either change the parameter or I just change the script but usually I just change the parameter in things like TeamCity and that's it. So I can change the text defined without changing the filing source control because that's knowledge that keeps changing about the system. [\[32:24\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1944s) And of course we want the builds to be run everywhere. So I don't I don't I shouldn't care what is the machine where the build is running on. So I always want to have a relative path. I never want to know the exact location. So all build scripts should be relative to the location where they are. They shouldn't know where they're located. This is actually a very big antiattern that I see in a lot of places. [\[32:55\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=1975s) One thing that I keep doing is that I have these scripts and then I extract just like I have extract method I have extract script which I usually do. So I would have one script call another script. This is a script that changes a lot of XML settings. So it configures a website and then at the end after it deploys it calls check site. Now what what you'll notice is that there is hierarchy here. [\[33:25\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2005s) So I can take something like a FinalBuilder script file and I can introduce a new developer into my script and teach them how the build works usually in a 10 minutes which is something that a lot of people cannot do because the build files are huge XML files of 500 lines which nobody can edit by but but one guy and that one guy or girl they're now the [bus factor](https://livebook.manning.com/book/elastic-leadership/chapter-3 "Dealing with bus factors (Elastic Leadership, ch. 3)"). Have you heard of the bus factor? The bus factor is a very important factor. It's how many people have to get hit by a bus before your project stops working. [\[34:00\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2040s) So a bus factor of one is the worst. Okay? It means that there's only one person who knows how to work with a specific technology. And that person, if they're sick, you're stuck. They get hit by a bus, you're stuck. There's always one or two of them in each project. And the idea is to make the knowledge sharable as quickly as possible, having them pair as quickly as possible. By making the build easy to understand, you can remove the bus factor and not have that one person who's in charge of the build process. You want the whole team to be able to be in charge of the build process and change their own structure. [\[34:41\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2081s) Another thing that happens is because we have all these builds, we have CI, we have integration, you might have acceptance test builds. When do we start coding? After we check in the code, right? A lot of people would wait an hour before they start changing the code again because the builds take such a long time. Well, one thing that I like to do is to have build waves. So my confidence grows better and better the more builds pass after I check in the code. So whenever I check in the code, I make sure that CI runs automatically and once that finishes, I make sure that either slow build or deploy to test runs automatically. [\[35:18\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2118s) So I have the first two or three run automatically. But I start coding after CI has passed and that gives me the feed quick feedback says everything is okay. Now let's do the integration test but you can start coding again. That's why I don't recommend combining into a single build the CI and the integration because that forces the developers to wait until the end of all the tests instead of wait until the end of the unit tests [\[35:51\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2151s) And that takes a lot of time from the project. Now there's another antiattern that keeps happening and you probably heard it in a lot of agile circles. don't break the build. Or when I was a just a beginning agile coach, I used to tell people that if they break the build, they have to wear a shirt that says I broke the build or they have to bring cookies or something stupid like that. Well, let me please ask you not to do that. [\[36:24\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2184s) You do not want to encourage people not to break the build. In fact, breaking the build is what the build is for. What's the point of a build? The point of a build is that it it breaks when you break it. It it's supposed to tell you something. It's just like a compiler. You're happy when a compiler tells you that you did something wrong. You don't want to wait too much. So that's why you want to have the builds. You want people to commit and to break the build. The only thing you don't want to do is to wait when the build is broken. So the antiattern should be that people wait too much when the build is broken and they assume that just one person has to fix it instead of the whole team. [\[37:03\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2223s) That should be a shared responsibility. If you encourage people not to break the build, one of two things can happen. First the is that they are afraid to check in code and so the the code check has become longer and longer, more complicated and actually the more more more chances that the build will break and when it does break it's going to have you're going to have a much harder time to fix it. The second thing that could happen is that people as they wait [\[37:35\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2255s) They will not ask for help because they they will feel ashamed that they broke the build. And so that actually encourages less social behavior because you don't you broke the bill so it's your fault. You should feel bad about it and so you should work alone to fix it. Or I don't want to break the bill but I'm afraid I will but I'm not sure and so I'm not sure if I should ask someone to work with me on that. [\[38:06\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2286s) It causes a lot of stress for people. Instead of asking for help, people might be just shy and just work alone even more and more and more. So it gets them to be a bit even more secluded and work in their own bubble. The point of the build is to share information. When a build fails, you should be happy. You should be like, "Dude, the build failed. Let's be happy. Let's do something about it." Never let anyone know that you feel bad about the build failing. [\[38:39\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2319s) You should feel happy that the build that the build fails because it means that you learned something. And yeah, back to the XML. If you if your builds do have a lot of XML editing in there, you've already lost. Not today, but maybe in three months or maybe in a year, you're going to get to the point where the XML has to be edited and your bus factor is gone or you have no idea what what space you've added or what uppercase letter you missed to make the whole thing not work. [\[39:09\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2349s) And if you will ever want to refactor your build, you're going to have a hard time. So, just to summarize, a beautiful build is when you can see the flow. You can see where the code goes in and where it goes out. You can easily change it. You can easily understand it. You can understand what each phase means and you can easily know when to continue coding again and when to get feedback from the customer. So everything should be easy. And if a build is truly beautiful, it's boring. [\[39:41\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2381s) Okay? A beautiful build feels boring. Okay? If your build is like very risky and very oh let's see what happens now when I check in everything becomes then then that's an antiattern because a release should be very boring. A release should be just clicking a button and say okay take a look now. That's what a release should feel like. It shouldn't feel like okay let's do a release. Okay let's plan a week where we do the release. So well you work on the configuration files and you make sure the servers are up to date and you tell the client you have to wait and you take down the system. [\[40:18\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2418s) That shouldn't it shouldn't be like that. It should just be a simple boring piece of clicking somewhere and that's it. You should be able to see all the parts of a build. So I should be able to drill down and see each part very very simply. But if I zoom out, I should be able to see the flow no matter what level I am. So I can always see the flow from the outside, but if I look in, it's just like functions in code where you can drill in, but the functions have good names. [\[40:53\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2453s) They're readable and they call sub functions inside. Or another way to think about it is like a newspaper. A newspaper has a title, it has a subtitle, it has a summary, and then it has the text. as for for each level you can get a different understanding of the system but you can choose at which level to look at it. Okay. So we have high level and low low-level patterns. The high levels are what you want the builds to be version aware. That means that you want the build scripts to be in source control and you don't want the you don't want the build controller to know anything about the structure of the code. [\[41:32\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2492s) You want the build to be commulative. That means that each build does one thing and it gets and it gets the assets from the other builds before it does it. We have build waves which are means that the bills get triggered one after the other. So that makes our confidence higher and higher as time goes by. But we can start coding very early. And we have a shipping skeleton which is the beginning of a project. But if you're in the middle of a project, you can still choose to do a shipping skeleton. [\[42:03\]](https://www.youtube.com/watch?v=WPSSx8RcvhU&t=2523s) You can say, "Okay, let's do a hello world, make it go through, and then we'll adapt our product and and and and replace hello world with our product and see what we have to add to make everything go." But you have to start somewhere, even if you're in the middle of a project. Low level, we we make sure that the scripts are readable. So, we extract scripts to make them readable. We we make sure that the scripts have parameters. They're not hard-coded. We make sure that the scripts don't care where they run from. They're always relative. ## Related - [Pattern: Shipping Skeleton](https://pipelinedriven.org/article/2014/3/2/pattern-shipping-skeleton) · pipelinedriven.org Roy's Shipping Skeleton build pattern: a hello world that goes through the whole release chain first. - [Release Compilation](https://pipelinedriven.org/article/2014/3/2/release-compilation) · pipelinedriven.org Roy's article on treating releases as compilation, the lesson's idea that release is the best form of compilation. - [Build Pattern: Cumulative Build](https://osherove.com/blog/2013/2/7/build-pattern-adopt-artifacts.html) · osherove.com Roy's Cumulative Build pattern, the artifact-sharing builds discussed in this lesson. - [Pattern: Script Injection](https://pipelinedriven.org/article/2014/3/2/pattern-script-injection) · pipelinedriven.org Roy's Script Injection build pattern, the build script injection covered here. - [Tests and Builds are Made to be Broken](https://osherove.com/blog/2013/1/20/tests-and-builds-are-made-to-be-broken.html) · osherove.com Roy argues breaking the build should not be discouraged, a point made at the end of this lesson. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 #### The Art of Unit Testing, 2nd ed. - [Automated builds running automated tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec1), ch. 7 #### Elastic Leadership - [Dealing with bus factors](https://livebook.manning.com/book/elastic-leadership/chapter-3), ch. 3 #### osherove.com - [Video: Beautiful Builds](https://osherove.com/videos/2013/5/17/video-beautiful-builds.html) - [The difference between continuous Integration tools and automated build tools](https://osherove.com/blog/2010/1/14/the-difference-between-continuous-integration-tools-and-auto.html) #### 5whys.com - [The Bus Factor - Why your ‘best’ developer is your biggest problem](https://www.5whys.com/articles/the-bus-factor-why-your-best-developer-is-your-biggest-probl.html) #### pipelinedriven.org - [Time to Main - Measuring Continuous Integration](https://pipelinedriven.org/article/2015/5/15/time-to-main-measuring-continuous-integration) - [Continuous Delivery Values](https://pipelinedriven.org/article/continuous-delivery-values) #### YouTube - [Start by Shipping : Shipping Skeleton](https://www.youtube.com/watch?v=8jeIwGzuqJ8) [Previous lesson Discussion About Pros and Cons of Unconstrained Frameworks](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/discussion-about-pros-and-cons-of-unconstrained-frameworks/) [Next lesson Summary](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/summary/) --- title: "Summary" url: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/summary.md" canonical: "https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/summary/" tags: [] author: "Roy Osherove" description: "Lesson 21 of 21 in The Art of Unit Testing and TDD in Java (Day 3), 0:35. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Summary 1. [Courses](https://courses.osherove.com/#courses) 2. [The Art of Unit Testing and TDD in Java](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) 3. Day 3 Lesson 21 of 21 Duration: 0:35 [Watch on YouTube](https://www.youtube.com/watch?v=fnMuiS0hn2c) ## In this lesson Roy Osherove ends the course by pointing to [artofunittesting.com](https://www.artofunittesting.com/ "The Art of Unit Testing (artofunittesting.com)") for more videos and free material, to his Twitter account RoyOsherove and to osherove.com for courses. He mentions that he is writing books about [beautiful builds](https://osherove.com/videos/2013/5/17/video-beautiful-builds.html "Video: Beautiful Builds (osherove.com)") and about [team leaders in software](https://www.manning.com/books/elastic-leadership "Elastic Leadership (Elastic Leadership)"). ## Transcript 80 words [\[00:02\]](https://www.youtube.com/watch?v=fnMuiS0hn2c&t=2s) Well, that's it for this course. I hope that you enjoyed. If you'd like more information, you can go to [artofunittesting.com](https://www.artofunittesting.com/ "The Art of Unit Testing (artofunittesting.com)") for more videos and lots of free stuff. You can also follow me on Twitter at RoyOsherove or just go to osherove.com if you want to get some courses or learn about other things that I do. For example, I'm writing a book about [beautiful builds](https://osherove.com/videos/2013/5/17/video-beautiful-builds.html "Video: Beautiful Builds (osherove.com)"). I'm writing a book about [team leaders in software](https://www.manning.com/books/elastic-leadership "Elastic Leadership (Elastic Leadership)"). and many other things. ## Related ### Also linked in this lesson #### Elastic Leadership - [Elastic Leadership](https://www.manning.com/books/elastic-leadership) #### osherove.com - [Video: Beautiful Builds](https://osherove.com/videos/2013/5/17/video-beautiful-builds.html) #### artofunittesting.com - [The Art of Unit Testing](https://www.artofunittesting.com/) [Previous lesson Continuous Delivery](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/continuous-delivery/) [Last lesson Back to the course overview](https://courses.osherove.com/courses/the-art-of-unit-testing-and-tdd-in-java/) --- title: "TDD Pairing Sessions - Building a Go Game" url: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game.md" canonical: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/" tags: [] author: "Roy Osherove" description: "TDD Pairing Sessions - Building a Go Game: 11 lessons, 10 h 50 min. A free video course by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # TDD Pairing Sessions - Building a Go Game [Courses](https://courses.osherove.com/#courses) 11 lessons 10 h 50 min 1 section [Start course](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/understanding-the-problem/) [Watch on YouTube playlist](https://www.youtube.com/playlist?list=PLH1g9ANe7JsI) ![](https://courses.osherove.com/img/yt/8riX4rG7Idc.jpg) Over 8 hours of hardcore live pairing. ## About this course Roy Osherove and Raymond Lim, who wants to build a Go game, [pair program](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html "How Do You Explain Pair Programming? (osherove.com)") a Go game engine test first in C# with Visual Studio, ReSharper and [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)"). Starting from an empty board, they add tests for removing surrounded stones, komi and finding a winner, taking small steps that remove one assumption at a time. Later sessions add a [DSL](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6 "Building a test API for your application (The Art of Unit Testing, 2nd ed., ch. 7)") for drawing boards in tests, try NCrunch and Mighty Moose, refactor into rules, strategies and removal detectors, and spend long stretches debugging their own test code. ## Related reading - [Replacing beforeEach() completely with factory methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2) · The Art of Unit Testing, 3rd ed., ch. 2 From the lesson [Understanding the Problem](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/understanding-the-problem/): Book section on replacing beforeEach() with factory methods, the same choice the pair make over setup methods. - [When should you remove or change a unit test?](https://osherove.com/blog/2005/4/3/when-should-you-remove-or-change-a-unit-test.html) · osherove.com From the lesson [Finding a Winner](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/finding-a-winner/): Argues passing tests should not be removed or changed, the reason the pair duplicate tests rather than edit them. - [Debugging Unit tests using the VS.net debugger](https://osherove.com/blog/2004/1/9/debugging-unit-tests-using-the-vsnet-debugger.html) · osherove.com From the lesson [Debugging Excursions](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/debugging-excursions/): How to step through unit tests in the Visual Studio debugger, as the pair do with conditional breakpoints. - [Avoid testing private or protected methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_160) · The Art of Unit Testing, 3rd ed., ch. 8 From the lesson [Mapping Moves](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/mapping-moves/): Book section on avoiding testing private methods, matching the choice to test komi through the public who-wins method. - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) · osherove.com From the lesson [Stoned and Board](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/stoned-and-board/): Four questions for finding the simplest thing that could possibly work, as the pair pick the laziest passing code. ## Curriculum Section 1 ### The Sessions 11 lessons · 10 h 50 min The section is a series of recorded pair-programming sessions in which Raymond Lim and Roy Osherove build a Go game engine test first in Visual Studio with ReSharper and NUnit. Their tests cover empty positions, removing surrounded stones, komi and finding the winner by counting owned cells, while the code is refactored into rules, winner strategies, a stone remover and removal detectors. Several sessions go into debugging, including line breaks that differ between machines and swapped X and Y positions in a DSL that draws the board in a string. 1. [Understanding the Problem Duration 1:53:39](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/understanding-the-problem/) The pair agree how to pair program, set up Visual Studio with NUnit, ReSharper and TestDriven.NET, and write a first test that a new board position is empty. They cover units of work with three kinds of end results, a ReSharper test template, factory methods instead of setup methods, and removing assumptions one at a time. Then they drive out removing a black stone surrounded by white stones, in a visually laid-out test, and debug an index out of range bug at the board's edge. 2. [Mapping Moves Duration 30:05](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/mapping-moves/) In session two Roy Osherove and Raymond Lim list the missing moves and features in an Excel file, with Raymond explaining the rules of Go. The list includes surrounding groups, invalid moves, switching turns, the winner, handicaps, board sizes, saving games and komi, which means there is never a tie. Aiming for a game that can be finished, they test that white wins by default because of komi, through a public who-wins method, since komi is internal. 3. [Stoned and Board Duration 30:14](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/stoned-and-board/) The pair look for the simplest test that proves black can win, and the Excel file explains scoring: points for territory, a point lost per removed stone. They consider an event log for calculating the score, but choose a test that adds stones so black owns at least one cell. The laziest code, where the last stone added wins, passes, so a new test has white play last while black still wins. 4. [Colors and Winners Duration 48:10](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/colors-and-winners/) The pair check whether a cell is fully surrounded by a color passed as a parameter, and add an empty color as the enum default because a new matrix is all black. A komi mode flag, off once a stone is played, keeps the default test passing, and logic moves into a new rules class. A broken large refactoring is undone and redone in smaller steps, and the board forwards get winner to the rules, explained with the Law of Demeter. 5. [Finding a Winner Duration 1:01:59](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/finding-a-winner/) In session three the pair remove the hard-coded corner cell from the winner check, duplicating passing tests instead of changing them and changing one assumption per test. Debugging shows the board starts all black, so they first write a failing test where white should win by komi, then fix the enum and an off-by-one edge check. They loop over the board to find surrounded cells, add an edge constant and remove the assumption that black always wins. 6. [Total Noob Fail Duration 1:26:57](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/total-noob-fail/) Session six starts with five tests failing on one machine but passing on Raymond Lim's, caused by line breaks in a string the test code splits. The first cell strategy, which really returned the last cell, becomes a strategy that counts each color's cells, and a planted bug shows the new test can fail. After removing the assumption that the surrounding color is white, work on two connected stones ends with finding X and Y swapped in the test's fill board helper. 7. [A DSL for our Tests Duration 55:07](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/a-dsl-for-our-tests/) In session five the pair turn on NCrunch, which runs the tests when the code changes and shows line coverage. For counting territories they write tests where one color owns one cell and the other two, but the tests pass unexpectedly and they cannot find out why. They build a DSL that draws the board as a string with numbered rows and B and W stones, parsed by splitting and trimming lines, and convert the other tests to it. 8. [A Refactoring Dillemma Duration 43:47](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/a-refactoring-dillemma/) In session four the pair use Mighty Moose, a free Visual Studio plugin that runs affected tests on save, and start replacing the komi mode check with the strategy pattern. Komi and first cell winner strategies inherit from a winner finding strategy base class that gets the board in its constructor, and the komi flag and current winner field go. The change breaks the test where white should win by komi when nobody owns a cell, raising the dilemma of whether counting points will replace the strategies. 9. [Debugging Excursions Duration 51:29](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/debugging-excursions/) In session seven a test fails on Raymond Lim's machine, and NCrunch coverage markers show the almost surrounded code never runs. Conditional breakpoints and moving stones away from the edge point to a bug near the edges, so they add tests near the top and left edges. Replacing the fill board call with add stone calls shows the bug is in the DSL, whose X and Y swap was never committed, and they start a check below the stone for vertical pairs. 10. [The Big Refactor Duration 1:28:13](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/the-big-refactor/) In session eight the pair refactor before adding a group of three, guided by don't repeat yourself and the single responsibility principle, since simple code forces thinking about tests. Removal logic moves into a stone remover class with a removal arguments parameter object, leaving the board to manage the stones. The checks become removable detector classes returning lists of position tuples, one looping over checkpoints, and the classes move to their own files and folder. 11. [New Features Duration 40:06](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/new-features/) The pair test that two stones which are not fully surrounded are not removed, and make the almost surrounded check count three edges of the other color and one of the same. The fix also checks a diagonal, which they call the board-scanning algorithm rather than a game rule, like dispersing the fog in DND games. They add test cases, then a check above the stone for vertical pairs, fixing out of bounds errors at the top edge by returning empty there. --- title: "Understanding the Problem" url: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/understanding-the-problem.md" canonical: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/understanding-the-problem/" tags: [] author: "Roy Osherove" description: "Lesson 1 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 1:53:39. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Understanding the Problem 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD Pairing Sessions - Building a Go Game](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/) 3. The Sessions Lesson 1 of 11 Duration: 1:53:39 [Watch on YouTube](https://www.youtube.com/watch?v=8riX4rG7Idc) ## In this lesson The pair agree how to [pair program](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html "How Do You Explain Pair Programming? (osherove.com)"), set up Visual Studio with [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)"), ReSharper and TestDriven.NET, and write a first test that a new board position is empty. They cover [units of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") with three kinds of [end results](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)"), a ReSharper test template, [factory methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "Trying the factory method route (The Art of Unit Testing, 3rd ed., ch. 2)") instead of [setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162 "Avoid setup methods (The Art of Unit Testing, 3rd ed., ch. 8)"), and removing assumptions one at a time. Then they drive out removing a black stone surrounded by white stones, in a visually laid-out test, and debug an index out of range bug at the board's edge. ## Transcript 13,279 words [\[00:14\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=14s) >> Okay. So are you familiar with how [pair programming](https://osherove.com/blog/2003/9/9/pair-programming-qampa.html "Pair Programming Q&A (osherove.com)") works? >> No, no, I'm not familiar. So the basic idea is that we are both trying to deliver the same product and so we take turns or we switch every few minutes. When one person is the driver, the other person is basically helping out. So you might you can start on the keyboard and try to create your vision of what the go game looks like. We can basically do it together and we can switch whenever we want to. [\[00:48\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=48s) Okay, >> that makes sense. >> Okay, makes sense. >> so just so you know, the way I like to do things when I'm doing [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") is that also I want to make sure that for example I get the I like to start with the code very very clean. So I remove all the using as well. So I just remove all the unused directives and also the class name should have a a good name here. >> what what should we rename it to? So, I was thinking the first test would probably be interacting with the board directly. [\[01:21\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=81s) So, like putting the stones on the board. So, I maybe like add stone tests. >> Add stone tests. >> I are you talking about just with general maybe board tests and then the scenarios would be adding stones. >> Well, let's start with what do we want to demo out of this session. Okay. >> What do you want to do? >> what was the issue that I was having problem with? I forgot. [\[02:11\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=131s) Well, the thing I want to demo out of this is interaction between multiple objects, right? So, >> yeah, but in terms of a deliverable product, what were you trying to accomplish? Oh, I was trying to accomplish a game that two players can interact with each other or well basically like I guess what you call like an engine where I could add in like AI to replace the charact replace a player but I wanted like a a full game for the go game. Is that is that what you were asking? >> Okay. So we can start with maybe full game tests see what happens. [\[02:46\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=166s) >> Full game test. Okay. >> So just F2 to on the class name. Okay. like full full game tests and that will also rename the file name in the solution it's for which is amazing cuz Visual Studio still doesn't do that after like four or five years I don't know why >> okay next we have to make this a test class so we have to add [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6 "More NUnit attributes (The Art of Unit Testing, 2nd ed., ch. 2)") to the package through add NuGet [\[03:17\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=197s) >> okay >> so do you remember how to do that just install package Now, at first, we're just going to write the tests and the production code in the tests >> and then we can refactor them out later. >> Okay? Right? >> Because the goal of this is to actually produce real code that works. >> It's not just to have tests. The goal is to >> I call it test driven development because the idea of the test is to drive development, >> right? [\[03:47\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=227s) Right. >> So, we're going to start with the happy path stuff to get things going so we can demo something so we can get feedback. >> Okay. >> Okay. So, we have NUnit and now we can add the test fixture attribute and the tests. >> I forgot does the test fixture go on top of the class? >> Yes. >> Oh, do I what's the shortcut? Was it alt enter? >> Control alt space if you want to get a nice completion here. Control alt space. [\[04:18\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=258s) >> I I did that. >> Interesting. >> Huh. >> The things next to it says alt enter. >> Yeah. But if you want to if you want to have a nice completion of let's see let's see what the ReSharper configuration here is. Hold on. Visual Studio. We're using the ReSharper 2x which is what I'm used to. And in there >> maybe I I misunderstood. I supposed to do test. Oh, sorry. >> Okay, you write it. [\[04:49\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=289s) Test. Just use the word test. >> Control alt space. >> I just start testing it and then control alt troll >> alt space. >> Control alt space. All right. How would you give it a try and let's see if you have a better >> Okay. Test fixture. Control alt space. No. Oh, yeah. For me, it's a Mac, but you know what? Let's just get rid of this and say fixture and be done with it. >> see, >> there you go. >> Oh, there you go. [\[05:19\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=319s) Now we have an alt enter here. Apply to all ReSharper shortcuts. From this moment on, it won't bother us anymore. >> Okay. >> and we can write our first test. >> Mhm. >> Okay. So, where do you want to start? What should be a good move to start with? >> So I from the books I read like the the first test is basically a very easy test, right? So >> it should be something that you can it should be I call it a [unit of work](https://www.artofunittesting.com/definition-of-a-unit-test "Definition of a Unit Test (artofunittesting.com)"). A unit of work is something that you usually start with a public method and it ends up with one of three [end results](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18 "Entry points and exit points (The Art of Unit Testing, 3rd ed., ch. 1)"). [\[05:57\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=357s) So you could have a value returned. >> You could have a state change to a system. So the system behaves differently. For example, it used to say X, but then I did an action, now it says Y. >> Or you call out to a third party like logging infrastructure, >> right? >> So, >> okay. >> What do you want to do? >> I think the first one should be adding the stone to a board. >> Okay. And then what is the change state? The change state is that that position you add it to goes from like there's no no stone to having a stone. [\[06:36\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=396s) >> Awesome. Okay, let's do that. So, so write the test. What's a good [test name](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html "Naming standards for unit tests (osherove.com)")? >> So, you the way according to what you like it, you like it with scenario and the result and with the method, right? Okay. So, it's not just a method for us. It's the unit of work. Remember, a unit of work can be something even bigger than a method. Could be a whole classes. As long as it's all in memory, you should be okay. >> Okay. So, add stone. >> Yeah. [\[07:06\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=426s) >> scenario. Well, add stone kind add the unit of work and scenario right now kind of sounds similar, doesn't it? >> Sure. Let's do that. >> Add stone. >> Well, add stone. Stone is added. You mean that it succeeded? Under what scenario happened? >> at >> right. Is that the scenario? >> Yeah, that might be good. That position is empty. Maybe I know that. >> Well, you can say to empty position instead of add stone to empty position cuz you're just repeating yourself there. [\[07:42\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=462s) >> Say it again. >> Well, you you don't have to say add stone twice. You can just say add stone to empty position. >> I see. empty position and then >> success or >> well no what what is the expected behavior now >> is it position is failed or >> position >> yeah position filled >> okay >> so now before we actually write this test >> Mhm. Now that if a position is filled, it also has a default value. [\[08:16\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=496s) Right. >> Right. >> So we can start with an even simpler test by having just checking the the state of a default position without doing anything. >> Okay, that sounds very interesting. >> So go just above that and see what we can do. >> so I guess the unit of work would be like query position or get position. Now, the question is, are is that what you're trying to do? Will you have a get position in the game? The get position status. [\[08:47\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=527s) >> Yeah, get position status. >> or is get position status something that's internal that's going to be used by something else? Does the user have to know the the status of a position? >> Yes. >> Okay. >> Get position status. >> Or just get position status, sir. Okay. >> >> now that's interesting. >> Well, empty position is the expected value, right? [\[09:18\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=558s) >> Right. >> initial >> you can say that yeah, initial position might be good. >> Initial status >> is empty position. Okay, that's good. I think that's a better starting test. >> Okay. >> Okay. So, let's put the other test. >> Do another one. Just comment it out for now. Just leave it there. You can comment it out. >> Oh, shoot. >> Don't worry. You don't just delete it. Who cares? [\[09:48\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=588s) That's why God created source control. >> yeah. Sorry. I'll just comment it out. >> Okay. Now, don't forget the test attribute here. >> Okay. Perfect. Now, if you're not sure how to run with this, you can start with the end. You can actually say, well, I know what I'm expecting. So, let's start from that. [\[10:19\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=619s) >> Something empty. >> Are you getting back an enum or just a true false? >> I was I was going to Well, I feel kind of tainted from what I written before I did the enum. >> Okay. So, >> can it have more than the true or false? >> Yeah, either white, black, or empty? >> White, black, or empty and go. >> Interesting. >> Yeah. So, the there's two players, white and black. >> And then if there's no stone, empty. >> Uh-huh. [\[10:50\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=650s) Okay. >> So, I I could either split in two methods like does it have a stone or not. >> Mhm. >> That's one method. The other stone is like what color the stone is. or I combine it in one and it's you number three, right? >> Whatever you want. Whatever is more readable to you. >> Okay. Okay. So would I do like a board like get position? >> No, no, hold on. You just just assume that you get back a result. [\[11:22\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=682s) Then we'll figure out where you get the result from. >> Okay. So I I do a result. >> Exactly. Now hold on. Something about the way you write stone empty. I'm saying what I'm thinking is that >> maybe stone is not a good enough enum name. It could be stone status empty. >> Okay. >> Why why would stone not be good enough? >> because a stone means that you're looking at a stone, not at a position. [\[11:54\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=714s) >> Okay. So it might be even position status instead of stone. >> All right. Position status sounds more clear. >> Okay. >> Keep on switching it. All right. Okay. And so no where are we getting the result from? >> So we get the result by quiring the board. >> Okay. So that so if you had the ultimate design assume that everything is already perfectly designed >> right >> how would the API look like? [\[12:26\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=746s) How would you get the quer? How would you get the result? Just just get the result from there. >> Right? So do you have to have an X and Y? What's the simplest position? What's the beginning position? Simplest position might be one one. >> Okay, >> because I was thinking the board goes from one to 19. [\[12:57\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=777s) Instead of doing a zero zero, I forgot what the term starting from zero. Start from one instead. >> Well, that's you're the go master here. It's your domain. So, >> All right. >> Okay. So, I wouldn't actually declare the position status as a result just before. I would just say position status result like this. So, oh, I tried to never mind. Different different shortcuts here cuz I'm running on a Mac, >> right? [\[13:29\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=809s) >> Just like that. Control shift L. >> sorry. >> Okay. >> Okay. So, position status result board get position and Okay. And how are you getting the board? You just create a new one. >> Yeah. >> Okay. >> Yes. do that. >> All right. >> No, it's not an eye board. >> Oh, my my bad. [\[14:01\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=841s) >> And it's also in the beginning. It's not an eye, just a board. >> Okay. So, we don't want to do All right. You're Okay. So, you we don't go with interfaces in the beginning. You start with the simple solution that works. Okay. You don't have to abstract away nothing because you don't have anything to abstract. You don't have any problem. >> Okay. >> Okay. Let the design emerge as things go. Okay, that looks pretty cool. I also like to separate these so that it's more readable. [\[14:32\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=872s) >> Right. The arrange acted a certain thing. Right. >> Exactly. And also, you'll notice that you call this get position status, but you felt more inclined to just say get position. >> Right. Right. >> So, which one do you like better? >> Like the >> Okay. >> All right. >> So, now we can make this compile and see it fail for the first time. >> Okay. So, >> so just just make everything compile by going to each to each of the red ones. [\[15:05\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=905s) Okay. and pressing alt enter and generating the class right here. Don't worry about it. Okay. We can always move it later. >> I see. >> Okay. >> What did Alt enter do? Did alt enter run it? Where? >> Alt enter. If you'll notice there whenever I'm on a red thing here, ReSharper has a nice lamp here. So, it tells me possible actions for a pro possible problem. >> So, it's like the genie >> just it always tries to help. So you can go to position status and generate that as well. [\[15:38\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=938s) >> So it's a class. No, it's actually not a class. Interesting. So you can create it as a class and then then turn it into an in I guess. >> Okay. Interesting. Oh wow. Okay. Wow. Very cool. >> Okay. Now we can go on into the get the position status. [\[16:09\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=969s) Hold on. Hold on. >> You're still in here. So, position status is what you want. Tab. Int what? >> Oh, >> int X. Int Y, I guess, right? >> X, right? >> And then tab. Int Y. Tab. >> Well, how come it adds a I next to it? I don't know why you have an I next to it. I have no idea. Okay. And and what I don't like is to have a notimplemented ex exception [\[16:39\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=999s) Because I like to have my test fail not because of something too obvious, but I like the test to fail for something that feels like a bug, >> right? >> So instead, I actually will return the wrong position status. >> So let's call it black. Okay. Okay. So now we can just still make it compile and then we should see it fail. So make it compile. Create an inner member empty. [\[17:15\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1035s) >> Well, how come it's not how come it's still red? >> H >> why is it still red? >> I don't know. Interesting. I don't know. Maybe just call it empty position. I don't know. See what happens. Maybe it's a special word or something. Control controller. >> Okay, we just call it empty stone. Maybe it's a just a save word. Saved word. Like special word. [\[17:58\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1078s) >> Okay. And just remove the empty one. Okay, interesting. >> Or maybe empty position is better. I don't know. What do you think? >> Right. You're definitely right. I was just trying to Okay. Okay. So now we can run this test and fail. So the first time you run the test, you just rightclick. Let's right click on the whole project. and run tests with TestDriven.NET. [\[18:30\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1110s) >> Okay, so if I run this, I should be able to see. >> Okay, expected empty but was BlackstoneOne. And you can also see the line number. >> Mhm. >> One fail. That's what we care about. Whenever you see this, you can also double click. So you can double click here and you have this nice marker over where you got to. Okay. So now we can go ahead and make this test pass in the [simplest way possible](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)"). >> Right? [\[19:01\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1141s) >> Okay. >> We just change this. Right. >> That is perfect. Okay. Now we can use alt R to rerun all the tests. >> Does alt R automatically build it? >> yeah, it also rebuilds it and it repeats the last action. >> Okay, >> perfect. Okay. So now we have the first loop in TDD. >> Okay. Now let's go to the next test that we wanted to write. [\[19:37\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1177s) Okay. So add stone to empty position. Position filled. >> Mhm. >> Okay. So now we're going to do a statebased change because at the beginning we get a wee know that initial status is empty. >> Mhm. But then the initial the the position is going to say that it's either black or white. Right. >> Right. >> Okay. So just don't forget to add the test. >> But you know what? Actually before that let's configure the environment a bit better. >> I want to teach you another trick. >> So I like to use the ReSharper snippets to generate tests. [\[20:11\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1211s) So what I'm going to do is I'm going to copy the whole test here. >> Okay. >> Crl C. And I'm going to go to the ReSharper Template Explorer. And now, do you see the icon for creating a new one? Like a plus. >> Is it this one right here? >> Yeah, new template. >> All right. >> Create. Click it. Okay. So, now we can we can close this window here. Word. Shift escape. [\[20:41\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1241s) I think that doesn't work. Can you drag the window? Cuz I can't. Drag the window to the side or something. >> This this >> the template is for window. Just drag it away so I can Yeah. Okay, perfect. >> Do you want to put this back? >> Okay, just close it. >> Yeah. Now I want to write the word test here. And every time I write the word test, I want this code this code to appear. [\[21:12\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1272s) Okay, for now I'm just going to press Ctrl S. Go back to the code. And now if you wanted to, we can just say test tab. We get this. >> Wow. >> Yeah, it's not it's not good enough yet. We want to make it a bit more generic for our taste. So >> I'm going to remove the whole thing here and going to replace it with dollar and dollar. That's a special keyword that says this is where the cursor is going to end up when you finished all the tabbing. [\[21:44\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1304s) But also dollar anything you put between two dollar signs >> becomes generic. So you can say this is the unit of work. Crl S to save it. And now if I go to test and I press tab, I get this. >> Very cool. >> Okay. Pretty cool. >> So, let's just go ahead and make the two dollar signs here and say scenario [\[22:18\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1338s) And tab expected behavior. And we should be done with creating a new test for now. So, control Z. Okay. Now if you press test we can have a nice one. So add stone to empty position [\[22:49\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1369s) Position is filled app. Okay. >> Okay. >> So it should be easier to write new test from now. I'm just going to delete this one. >> Very cool. >> Okay. Okay. All right. So, we'll start with the assert K. [\[23:37\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1417s) Oh, that's good. >> Press escape. Wait a minute. Which stone? How do you know it's black? >> You're right. [\[24:23\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1463s) Now, this is where it starts to make a less sense, >> right? Because can you add a stone to an empty position status? Can I add a stone? Oh, like empty position status. Well, it it doesn't sound nice in code, I guess. >> Mhm. >> It would basically be like removing the stone. We resetting position. >> Yeah. >> Right. Okay. >> Interesting. >> So, >> it might tell us that maybe the design is kind of problematic. [\[24:54\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1494s) >> Okay. >> Maybe we need a different different enum for that. Okay. >> So now you can say well before changing something just say what you wish the API looked like. >> Right. So instead of position status, you can just say stone type or something. Yeah, stone color. Awesome. >> Mhm. >> another type to think about is just adding the stone itself, which already has a coloring status, [\[25:26\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1526s) Whatever you want. >> Oh, you mean like a stone object? >> Yeah. >> What do you think? >> I I think no, because the stone is not going to have much of anything else. It's just going to have a color. Okay. Okay. >> To just be >> sure. >> I mean, is that how people normally do it? >> there is no how people normally do it. That's the point >> is that you start out with something and it needs to be [\[25:56\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1556s) Maintainable later, >> right? >> Okay. So, add stone to position with stone color black. And pos and I think that what you get back from get position status should be not not empty instead of black zone. >> Okay. >> Right. >> Does that make sense? >> Okay. Yeah, that makes sense. Now the nice thing about this is that since the most of the design doesn't exist yet, we can easily change it and it's going to be cost us much less. [\[26:45\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1605s) What do you think? >> Field does sound nicer. Right. >> Okay. So now we get to make this compile and see it fail. create the class and then turn it into an in. Yeah. [\[27:29\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1649s) Oh, I forgot to tap the >> Mhm. So, just click on Yep. Stone color. Hit X tab. It's adding a I >> don't know why. I have no idea why. >> How do I How do I skip that? >> Just tap by press. >> I think it's just enter. All right, cool. >> Okay, just make it not do anything, right? [\[28:02\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1682s) >> Just remove the whole line. It still won't compile because you can see all the red stuff over here, right? If you can see red means it's not compiling. You don't even have to try to compile it yet. If you can see red in this square, it's not going to be able to compile. I see. >> Okay. >> Okay. So, let's add this one. Just failed. And >> why still says red? [\[28:33\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1713s) >> Yeah, it's weird. Maybe it likes a comma next to it. No, >> let's see. No, that shouldn't be a problem. Position status filled. Not sure why call it filled position. Let's see. Let's wait. Let's see what ReSharper tells us. Alt enter. Add argument name expected. [\[29:11\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1751s) No, that we don't care about that. I mean we can say basically what it tells us we can do that. See that doesn't make a we don't care about that for now. But we can say filled position maybe equal space fill position. I don't know why I have no idea. All right. [\[29:42\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1782s) >> okay. So, now we should be able to rerun all the tests and one of them should fail. >> Right. >> Right. Right. >> Okay. One passed, one failed. So let's make all the tests pass in the simplest way possible. >> So, what's the simplest way possible? [\[30:21\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1821s) >> adding a variable. >> Nope, that's not the simplest way. >> Is that a way? >> I mean, yeah, I guess so. Maybe it is. >> what what was your was what you were thinking? Well, at the beginning I was just thinking of of of putting Yeah, but you have to save the value so that get position somehow saves it. So you can just make return position status return whatever is in the variable at the top. >> Right. >> Okay. [\[31:04\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1864s) I think you have some extra plugins trying to to add stuff. Something probably with C++. >> No, it's I keep on pressing cap caps lock cuz I have caps. >> So just yeah, you can reenable the caps lock thing if you want. >> Oh no, it's fine. >> So position status will be filled. Awesome. >> And initial >> alt R. >> Yeah, of course. No, no, no, no, no. That's That's already too complicated. [\[31:35\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1895s) >> That's too complicated. >> Yeah, you can make all the test pass without that, right? >> You agree? >> M I don't think so. >> Okay. >> But we'll try. >> Oh, yeah. I agree. I agree that that's missing. Sure. So, you have to add that the default. I agree. >> Yeah, because I set it. >> Mhm. True. >> All right. >> Okay. Two passed. Now, obviously, this is an amazing and beautiful solution. It's not good enough. [\[32:05\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1925s) But we can also refactor because we no longer need the black stone here, right? >> Right. >> We can just remove that. >> Let's see. Did we break anything? >> Nope. >> Cool. And is there anything else? We probably need the white, but we'll take care of that when we need it. So obviously this is not good enough. Right. >> Right. >> And what's not good enough is that [\[32:36\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1956s) I mean can you can you put in words what what you want to fix here? >> Well given position X Y. >> Sure. >> We're only checking one position. >> So we're always assuming the same position, >> right? >> Okay. And that's the big problem. And now the way I I see TDD these days is that you start with the simplest things possible which means that you make as many assumptions as possible and then you remove each assumption one by one just like peeling an onion and each one is makes the code more and more generic. [\[33:13\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=1993s) >> Right? >> Okay. So now we can remove the assumption that we always know the position. So we can write a test with a different position. Before we do that, we have to make the test a bit more maintainable cuz right now we have a maintainability issue. Can you see it? >> we're declaring a board every time. So, we have a setup fixture to initialize the board. >> Oh, why why is it a maintainability problem? [\[33:44\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2024s) >> It's a duplication. It's duplicated in both methods. Redundancy is that the word used? >> Well, yeah, it's redundancy, but the it's definitely that, but the problem is that later we can have we can add a constructor to board >> and then we'll have to fix all the tests with that. >> Okay. Right. >> Okay. Now, I don't use [setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_171 "Setting up and tearing down (The Art of Unit Testing, 3rd ed., ch. 9)") anymore. I'm actually writing that on the second the second edition of my book is that I'm trying not to use setup anymore. >> Okay. >> Because if I use setup method, then people will have to read the test in both places, [\[34:18\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2058s) >> right? to understand what's going on. >> I remember reading about that in someone else's blog. >> So, I refactor into a [factory method](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "Trying the factory method route (The Art of Unit Testing, 3rd ed., ch. 2)") instead. >> Crl Alt M. Let's see if that will work. Create a method. Make board. Okay. >> Okay. And the same here. [\[34:52\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2092s) Alt R. Let's see if we didn't break anything. Okay, so that's the basic stuff. It can be static for now. We don't have to do anything about that. Cuz it's part of the tests. But now I don't need a setup method and I can see exactly where board is created. Oh, I see. >> Okay. >> Okay. Very cool. >> Okay. So, let's remove an assumption about obviously the position is always assumed to be the same. [\[35:22\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2122s) >> Right. >> So, what we're going to have to do is we're going to write the same test with a different position, >> but we're going to expect >> an empty position. >> Do you agree? >> Right. Is is it going to be the same test? Really? >> well, there could be we could reuse one of the tests to do the No, I think to to get it to fail, we probably need to add a different test where we add a stone to a position, but check a different position to make sure it's [\[36:02\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2162s) Still returns empty position. I'm not sure. Maybe is that is that answering the question? >> Yeah. Yeah. I'm trying to see if we can reuse this test or not. And would it be readable if we did that? Okay. You know what? Let's create another test for now and see what how that looks. Right. Because if we reuse the test right now, it's still going to pass. >> No, I agree. I agree. But we can add another assert or we can replace the assert and have a parameter to the test where we can say add to this position check that position. [\[36:40\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2200s) But we still want to check the original position. So I guess we need a new test. >> I agree. >> Okay. So create another one or unless you want me to do it. >> I want to watch you do it. >> Okay. Ctrl W. Let's see if that will work. D. But you know what? I don't like duplication. But I'm going to write another one with the with this. So add stone to [\[37:22\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2242s) What would you say? Add to empty position. Empty position. other empty position is unaffected. I guess that's one way to think about it. >> Okay. >> I agree. But I think this should probably be a lowercase a let's see. [\[37:53\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2273s) So we would have a make board. Crl altv to extract a variable from that. Ah control shift space doesn't work here. Huh? Position [\[38:27\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2307s) Is it? Oh, stone color. color black one and one. It's almost the same test. >> or get position status of one and two. >> Mhm. and Ctrl AltV again to get the status [\[39:02\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2342s) What do we have? We have a position status dot empty from status. Okay. Alt R. Two passed, one failed. Okay. So why don't you try and fix it now? Okay. All right. So, is it [\[39:33\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2373s) >> now remember you have to fix it in the simplest way possible. So, you can make as many assumptions as you want. >> Okay. The thing that comes into mind for me is just putting it in a two-dimensional array. >> Okay. >> Sure. or a list of tuples. Actually, maybe a list of tuples is actually even simpler. So, [\[40:08\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2408s) >> as long as it's simple and readable, >> we know that there are 19 rows in each ver vertex. >> Okay. >> Are do we >> is it 19 by 19? >> Yeah, it's 19 by 19. I wasn't sure if that was not stable enough. So if I make constructor I mean [\[40:59\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2459s) Shoot. guy >> and then what will everything pass now? >> No. >> Obviously because we haven't used that, >> right? I can make this incorrect for now, but I already know that minus one. [\[41:34\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2494s) >> Why is minus one? >> Because we're I'm not doing a zero index. Is that the >> I'm doing a one index 1 through 19 instead of 0 through 18. >> Then wouldn't it be position status of 20 by 20? But then you would have 0 to n 0 to 19 which would make it I mean the length of the board is >> okay >> 19. >> Who cares? Let's make it let's make it pass. >> Let's not worry about it now. Can always change it later. [\[42:06\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2526s) >> Right. Why are you setting the position status here in get position status? >> You're right. I I was not thinking clearly. I think you should turn on the the caps lock for you as well cuz you keep hitting it for for control >> breaking up for me. I can't >> Yeah, I'm saying that you should enable your caps lock to be control again if you want because I think it's hurting you. [\[42:43\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2563s) All right, >> there we go. >> Okay. Okay. Now everything is passing. [\[43:14\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2594s) How can we make things a bit more readable and maintainable? So I would say that 19 we can make that into a const for example. >> Right. >> Mhm. >> So we could that do that. Sorry. >> Oh, >> you going to have you go ahead and do that be faster. Do you how did how did you do that when you extract it out? Was it controlm? [\[43:45\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2625s) >> Well, if you're not sure, you can always use your control shift R to get a menu of what you want to do. If you want, you can just select the 19. Hold on. Escape. Okay. I'm pressing escape here. Of course, it doesn't work. Yeah, I I switched three keys around. >> Control, shift, R. Nope. Which key did you switch? >> So I switch caps lock with control because it's the biggest key. [\[44:17\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2657s) Yeah. >> And then I have my control key as the escape and I have my escape key as the caps lock. >> Oh dear. That's why some of my shortcuts don't work. Okay. So anyway, >> maybe >> control shift R in this >> control shift R. >> You see in extract method introduce field or move to resource introduce field for now. Replace two occurrences [\[44:49\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2689s) Obviously. >> what will be the name of the field? >> Board size. >> Okay. And you can make it yeah private I guess. >> Sure. >> Okay. >> Why is it making a static? >> that's the default but I can just say private const int and then make it uppercase. [\[45:20\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2720s) >> This one uppercase. >> I'm pretty sure there's an uppercase shortcut but I'm not sure. Just a just F2 to rename it or board size uppercase. Let's see. XUS one. It's always minus. I don't like this minus one thing. I have to tell you. >> It's kind of weird to me. >> It's unreadable. [\[45:51\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2751s) Mhm. >> How do we get rid of the minus one? Just make sure we didn't break anything. >> Yeah. >> Forget about the implementation of the board for now of the array. How do we get it minus one? >> I'm trying trying to think what's the easiest way to make it pretty. If I don't have to use minus one, I can make the board size bigger, can't I? [\[46:25\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2785s) >> Yeah. But then I guess when you treat like the argument zero, >> but I don't have a test for that, so I don't care. Remember? >> Okay. >> If I wanted to care about it, I would write a test for it. >> So, we could do that the next after we fix the make things more readable. >> Okay. >> Okay. Remember, I want things to be readable. So, I can always check for I mean, it's not like people can't send an x of minus one if they really wanted to. [\[46:56\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2816s) Right. >> Right. >> And I'd still have to take care of that. >> So, what if I wanted to do this? I mean, for me, it just might makes it more readable. Other people might not like it. But that's the nice thing. You can make decisions about your personal taste. Alt R. Let's see what happens. >> Mhm. [\[47:28\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2848s) >> Actually, we can make it still 19. Do we have to change it? >> Because we don't have a test for the boundaries yet. >> True. So now we can write tests for what happens what kind of message do you get when you're outside the board boundaries? Okay. >> Mhm. >> But I think that's pretty read readable. >> so we can write a new test that says, well, if I'm adding a stone to something that to a place that doesn't exist, we should be getting back [\[48:01\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2881s) This specific message, >> right? >> But you know what? For now, I usually try to worry about these things later. So what because I try to go through the happy path first so I can say >> what happens when you're out of board position. >> Okay, >> I see. >> And then I can worry about it later. >> Okay. [\[48:32\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2912s) Okay. So let's move on to more exciting things. You where are we going with this? Let's let's get closer to where you were what you were trying to ask me. >> Okay. I I don't think I understand your question. >> you sent me an email. How do I [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") this behavior, etc. >> Right. >> Okay. So, >> what do you want to Let's try to recreate your scenario. Are we close there to that or do we need to anything else >> to get to your scenario? [\[49:06\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2946s) >> So, Well, we we still need to work on it a little bit, of course. >> Okay, let's add a couple more features. >> What do you want to do next? Which feature do you want to demo next? So we I want to [\[49:37\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=2977s) Add enough stones in the board and then after you eliminate a liberty for one stone, it disappears. So it would be like adding Well, I'm not sure if that's the next simplest one, but that's where I'm trying to head head towards, right? >> It sounds pretty simple. So exactly what you want to happen. >> So I want to set up the board so that there's a black stone surrounded by white stones. >> Sure. >> And and then when you add the last white stone, the black stone should be removed. [\[50:08\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3008s) It should be removed on the next pulse or exactly after that? >> Exactly when the white stone is added. >> But should there be an event when it's removed? >> what does it mean that who removes the stone? >> The board. I was thinking the I was thinking the game the game removes the removes the removes the stone and the board just acts dumb to it. >> Sure. [\[50:39\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3039s) Okay. So, why don't you write a test for that? a simple test that that uses the code the way you wish that the user would use it, right? Assume that the API is already there. You're just using it, >> right? >> To write a new test with the with a template. Yep. [\[51:10\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3070s) >> Where does this all start? Is it you add stone? >> No. So this is this would be like more a level above the just adding the stone. It would be more where the player adds the stone where does adding the stone and it also does checks. Right. So you want to add a stone to you want some kind of well so you what I'm trying to understand is [\[51:45\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3105s) Do you you can still add a stone to the board and then have like a an attached engine to the board that does all the thinking for you or you can initialize an engine >> with the board. It doesn't really matter, >> right? >> But you you're saying that the the the logic should be in a separate place. >> Yeah. >> What I'm saying is for now make the logic in the board and we can extract it later. >> Okay. That that would make it simple. >> Simplest thing that would work. [\[52:17\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3137s) >> Okay. You're right. So it would make it part of the add stone >> for now if you want. Yeah. >> For now. Last thing scenario is eliminate liberties or how how would you say I don't you just surround something? Yeah, that sounds nicer. around [\[52:48\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3168s) Opposite color stone. Maybe here remove What do you think? >> Does it get removed or does it get replaced? >> It gets removed. >> So it becomes empty. >> Becomes empty. >> Okay. So, [\[53:21\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3201s) So we did a make for and what was the nice shortcut that you did? Ctrl AltV to extract a variable V. Very cool. So, this Oh, this is also part of the setup. So do that. So let's put it in the middle. So [\[54:14\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3254s) You can just press Ctrl + D to duplicate a line, by the way. >> Oh, really? >> Try it. That's just let me try that. >> Oh, very cool. Very cool. >> And then you don't lose whatever is in your copy buffer. >> Oh, wow. That's even cooler. That is very cool. Okay. And then the action would be [\[54:47\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3287s) >> So that's the top row. >> So this this would be the action that finally does the removing. >> But doesn't stone have nine blocks to fill around it? No, you only need the the how you horizontal and vertical diagonals you do not need. >> Okay. >> Mhm. >> All right. So, let's see. [\[55:18\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3318s) Okay. I would write this test a bit more clearer where the position of one two three two one to be left position right position bottom position for example >> okay see what I mean >> I'm trying to figure out how I would I add a comment to indicate that or would I >> well just the just the just the X part or the part the other part [\[55:50\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3350s) Maybe a comment I'm not sure. >> So, you mean like bottom? >> yeah. >> Well, actually this one would be this one would be left X, left Y. Is is this what you mean? Well, just the one that may that that tells me when I that I visually can see where would it be? What if we just put the lines visually around [\[56:21\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3381s) Can you make one line more to the left? One one line more to the right. One line. See what I mean? We can actually position the C code so that we visually see which line is above or to the right of which line. >> Okay, that's that's interesting. >> I want the test to be almost visual. >> Wow. Okay, that's an interesting concept. >> Kind of like this. >> Yep. [\[56:55\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3415s) That's very interesting. Just above it. Yep. Oh, that did not work. >> Yeah. >> Wow. This looks pretty cool. >> It is very cool. I agree. Okay. So now I can actually scroll as a reader of the test. I can scroll and I can see that this last one seals the deal. [\[57:30\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3450s) >> Yeah. >> Okay. >> This does this definitely does make it more readable. Very interesting. >> All right. >> [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)") is one of the most important things in the test because the these tests assuming it's a real software they have to last for 10 years. >> Mhm. Five years from now, someone's going to read your test, they're going to see this. >> Okay. >> So, readability is really important. And it also helps you figure out that you're in the right track with the numbers, [\[58:02\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3482s) That your test isn't wrong. variable just before the semicolon. >> Control alt v. >> Control >> alt v alt >> v >> alt v. Yeah. For variable. >> Okay. All right. [\[58:45\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3525s) I don't know how it gained the double parenthesis. Now make it compile. We We're missing the white, right? Okay, let's see what happens obviously. Okay, now I think that to make this possible, [\[59:17\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3557s) We have to start adding more information to each each area, right? Not just position status, >> but the position status and the color, >> right? which to me represents a stone >> in a way. >> Mhm. >> No, >> you're right. >> or just a structure, whatever you want. But now we have to make this passable in the simplest ways possible. So let's see let's see what we can do. [\[59:48\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3588s) Let's go to the production code. Okay. Okay. I'm going to I'm going to pause this for a second. I'm going to take a little break. And I'll be right back. >> Okay, >> we're back. >> All right. So like you mentioned we had to put in more information but the interesting thing is that if we do the same thing we did with the position status matrix is that [\[1:00:23\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3623s) >> checking like if we initialize another matrix for the stone color is all everything is going to be set as one color initially right >> interesting. Yep. >> But since it's empty, we don't care about it, >> right? So, we don't care about that right now. So, we just just go ahead and do it first. >> Well, we can do another So, you're saying just create another matrix. Why don't we just put different an object with more information in the matrix itself, [\[1:00:58\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3658s) >> right? So, create or create a mat you may create a matrix of a different kind of object, a more object with more information, right? >> Yeah. Instead of instead of position status, >> we can create a matrix of stone info or something. >> Okay. >> What do you think? >> Right. So, I think that's a good idea. I think that that's a good idea to head to. So, would would I start doing that right now? >> Well, there is no right way. We we can start doing that right now. [\[1:01:28\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3688s) Remember, the point is to make the current test and all the other tests fail in the simplest way possible. So we have to make as many assumptions as we can so that we don't forget to to add those tests later. Whatever if we if we put in too many if we remove too many assumptions if we make the code too generic we might not feel any need to write tests for it later. >> Yeah. But I mean like right now one of the tests is failing. Should so should we take that out refactor the code and bring it back? [\[1:02:00\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3720s) No, no, no. We have to make everything pass because we have to the the fact that the test is failing gives us focus. >> Okay. >> Okay. It tells us exactly what we're trying to to achieve. >> So we we have to make the the point is here to make the all the tests pass. It's not to refactor, it's to make all the tests pass. >> Okay. >> So whatever we have to do, we have to do. If we have to change the internal board, we can do that. >> Okay. Well, we can do many other things. [\[1:02:30\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3750s) I mean, we can have an an extra board internally. Whatever you want. >> All right. Well, I think the easiest way to first make it pass is to make not replace the object, replace it with the object, but copy and make it the stone color matrix. >> Okay. [\[1:03:01\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3781s) But instead of position status, it takes in the stone color. >> Sure. so then add stone position. The best best way to do it for now would be [\[1:03:34\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3814s) Just add another line I guess. >> Right. >> Just duplicate it and then change it to some color. Right. >> You forgot to use control D, my friend. Oh, >> I'm not saying that's the only way, but it's a good tactic. >> It is. I agree. But that's not be enough to make that test pass. [\[1:04:04\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3844s) >> No, because get positions. Well, no. This is where we just have to add the the calculation. Let's just add the calculation right here in the ugliest way possible. It doesn't have to be ugly, but in the just just do it here. We can refactor it later. >> Okay. >> So now just figure out if some if if the if there is if the stone on the board and we know which stone it is. Right. >> Right. >> Let's figure out if that stone is is surrounded. [\[1:04:35\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3875s) >> Okay. So just using hard-coded values. >> Yeah. That's an assumption we can make and then later we can say aha what if it's a different stone? Okay. >> So making the assumption will make it easier for us to figure out the algorithm. Then we can later make it more generic. That's the point as well. Just just figure out for this test and all the others. Okay. So the simplest would be it's going to be interesting. [\[1:05:29\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3929s) No, the end should be Yeah, sure. >> Say again. >> No, no, I'm just I'm just blabbing away. >> Yeah, I think you're on the right track. All right. You forgot to do an equals equals just before. [\[1:06:15\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=3975s) >> Yeah, actually you ReSharper can help you out with that. >> Oh, really? >> You see the the the pencil there? If you put >> split, flip. Let's see what happens to split. >> no. >> That looks dis that looks disgusting. >> Okay, never mind. Forget I said anything. >> Maybe it's cuz I didn't complete it yet. But [\[1:06:54\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4014s) What's the stone location? Two and two. >> Yeah. >> Awesome. Yep. Awesome. >> Okay. But >> that doesn't make any sense. We have Yeah. Yeah. Actually, it does make sense. I guess >> I think the the problem is that the initial position is probably all white or no, is it all black? >> No, it's all white. You're right. You're right. >> You know what's cool [\[1:07:26\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4046s) Is that I think at some point we can just get rid of the other matrix. >> Yeah, at some point >> I think actually a couple of tests from now. I mean we don't have to do anything with the other position matrix if we can just check the color of the stone color. >> Isn't that cool? >> Yeah. >> Cool. Okay. So we made all the tests pass, right? >> Right. Obviously not great because it's not readable, not maintainable, but we can at least go ahead now and say, okay, let's just Oh, you have the control and set to something else, right? [\[1:08:07\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4087s) >> No, let me >> hold on. >> Control. No, yeah. Yeah. >> W I can't work with this. Never mind. So what I want is to select the whole thing. Say okay. Ctrl Alt M extract methods. Ctrl Alt M. [\[1:08:38\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4118s) >> It's not how it right now. >> H. >> Oh yeah. Control Alt M. >> Caps lock. >> I tried with the caps lock. Okay. Just extract method. Good. >>. >> What happens when you have keys bound to anything else? Just press just undo. Undo. If I can't use control, I can't do anything on your machine, dude. >> Let me let me just move the script. [\[1:09:11\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4151s) There you go. Okay, let's see if I can do something now. Ctrl AltM. Yay. Extract method name. Let's what do you what would you call this whole thing? >> let's call it check. Check neighbors. >> Check. >> Checking. It's not just checking. >> it's actually removing >> right. So removed surrounded stone. [\[1:09:43\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4183s) >> Okay. remove surrounded stone. Cool. Now we can go ahead and say surrounded stone. Let's see. We didn't break anything. Alt R. Okay. Now let's write another test that proves that other stones can be surrounded as well. I think we're getting somewhere. [\[1:10:14\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4214s) Okay, >> we can make this a >> sorry, >> you want to reuse that test. >> do you know how to reuse tests? >> Right. The test case. >> Exactly. >> okay. So, let's have you used test case before? >> Yes. >> Okay. The difference is that this time in our test case [\[1:10:46\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4246s) >> we have to calculate the neighbors. >> No, we don't I don't want us to calculate anything cuz we could have a bug and when you're calculating things in the test >> most likely you're also repeating production code and if you get the calculation wrong you actually creating the bug and then the test will pass. So, we would have to list out the X and Y for all the neighbors, too. >> Yep, I guess so. >> Okay. >> Okay. So, the way I would do it first is to say [\[1:11:17\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4277s) Just go through each of them one by one and say, I'm trying to see maybe we should just write another test. I think it will be more more readable. >> Okay. >> then then stuffing the whole >> That's probably the easiest way to do it. >> Yeah. >> Oh, properties. God, so many windows. Start using Vim and less windows in Vim. Control V. [\[1:11:48\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4308s) Color stone 2. And here we're just going to change just figure out give me a different one position. I want to be able to see the difference between these two tests so that everything is just one off. Maybe just one line below. >> Are you What do you mean one off? Just change like a two to threes. >> Well, change all the y's to plus one. I'm guessing that that's all we need. Right. [\[1:12:19\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4339s) >> Right. So, we would say this is a two, this is a three, and this is a four. Right. >> Right. >> And this is still >> that would be a three. >> And we can see them cuz they're right next to each other. So, it shouldn't be a problem. I can figure it out. >> and then we have a 2x3. >> Yes. Alt R. [\[1:12:51\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4371s) >> Okay. >> Or Okay. So now here's the cool thing. We get to go to the production code and just make it a bit more generic. Remove some of the assumptions. So we can say just get get this as a parameter. So I can say Ctrl AltP for it parameter. replace. Yeah, we can use six. Six occurrences. >> No, just one occurrence for now. [\[1:13:23\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4403s) >> Yeah. >> X. >> Yes. >> and control P for Y. And now everything else is just a calculation. Right. >> Right. So it will be faster if you just do all the cuz I'm doing it remotely. If you just make all the differences [\[1:14:24\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4464s) Whoops. We got a bug. All right. We need to change this to Y. But this still this is also still going to fail. And then it's supposed to be check all the neighbors. Actually, it's probably going to be more. >> Wait, hold on. What? >> Well, it's because >> Are you just renaming it? >> No, I'm not going to rename it. I was going to control D. Shoot. I was going to control D. [\[1:14:59\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4499s) Oh, this is really really really ugly code. >> Don't worry, just make it work. We ju we do we really have to use all of these. >> >> we just have to figure out just check specific stone, don't we? >> Right. >> Just 2 by two or 2x3 or Oh, we have to make it work for both. Right. >> Interesting. [\[1:15:30\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4530s) But we still have a bug. >> Yeah. Yeah. >> X - one, X + 1, Y - 1, and Y + 1. We didn't check the Y and X itself. [\[1:16:13\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4573s) What do you think? We can also debug if you want to. >> let's let's go with how do how do you debug with the Okay. So, you basically put a break point and then you go to the specific test. Actually, what I'm going to do, I think we have a way to to see multiple windows in Visual Studio at the same time, right? >> Yes. >> you split it, right? [\[1:16:45\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4605s) >> Yeah. >> vertical. I want vertical one. New vertical tab group. Okay. >> The thing is I don't know if it opens the same file in >> Oh, that sucks. Never mind. Okay. But we still want to go to the test. [\[1:17:16\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4636s) We can close this maybe so we get a bit more view. Ah let's see. So you can go to this test and say test with right click on it. Test with debugger. >> Nice. Okay. Cool. >> Cool. >> Okay. But remember we if we want to debug a specific breakpoint [\[1:17:50\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4670s) >> Mhm. Then we could just move forward until the fifth one or the middle one. >> fifth one or oh the middle one, right? >> So I want to I I want to do something specific. I mean if we look at the specific test by the way I'm pretty sure we don't have to do everything. We always have to check just the one above. >> I mean it's always we have to check with this one. >> We only have to check this one. Right. >> Right. So we can always check the one with x and y minus one, [\[1:18:24\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4704s) >> right? >> So that should be sufficient, >> So I'm maybe the the test I mean the maybe the production code is wrong. If we look at the >> we can make it simpler. >> Yeah, I mean let's maybe we're just getting the whole thing wrong. Simplify. Okay. I mean what if we just remove surrounding with x and y minus one. >> Okay. >> I we already have that [\[1:18:56\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4736s) But we we know that this one is supposed to work. Right. >> Right. >> And we we only have to do it on this specific thing. We don't have to break here. Actually, we do. What we don't have to do it another break point here. So now we can if we just run this test [\[1:19:35\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4775s) It actually passes. Interesting interesting >> maybe we don't need to debug at all. Yeah. Five pass. You see that? >> I don't know how that does anything, but >> Oh, well, welcome to programming. Right. >> Right. >> Okay. So, we know >> I know why. Why? >> Actually, no. I don't know why. >> But that's the cool thing is that because we can make assumptions, we can make small strides towards something. Now obviously we know that we're missing checking the other things because if we add things in the different order. [\[1:20:10\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4810s) >> Yeah. >> Right. >> It won't work. So now we get to write a test that proves that if you add things in a different order stone add stone let's say above >> okay >> above and surround opposite color stone remove opposite color stone How's that? [\[1:20:43\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4843s) >> Right. >> So now we can simply change the visual markup of the test to say aha. But now we can't write the test in a visual way. How's that? >> Yeah, it doesn't look as pretty. >> Yeah, but we we can still do it in at least Ctrl X. >> We can do is Yeah. Remove the top one and add it. >> And then say >> in another line below. >> Yeah. [\[1:21:17\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4877s) I don't know why to remove the whole panel. >> It's possibly because the line above it. Yeah. Okay. Okay. So now we can see 1 2 3 four and this is the fifth. >> And now running all the tests. Alt R should one of them should fail. >> Right. >> Five passed, one failed. And now we can just go and and [\[1:21:48\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4908s) Slowly but surely add just one more check. Right. >> Right. >> Ctrl + D. Add a Y + one. Right. >> Let's see what happens. Alt R. Yeah. Okay. You want to try the next two ones? >> I still I still don't understand why the other one did not pass. >> you know, we're human. We will never understand. [\[1:22:18\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4938s) We can only just assume that we're stupid and then do things simpler. >> So, would it make sense to just exhaust all the options? >> We We don't have many. We just have four, right? >> I mean, yeah, like the other two options. We have to we have to have other because each one of them is basically a feature in the application. Right. >> Right. Right. >> Sounds like you have a clicky keyboard. Are you using like a DOS keyboard or something? [\[1:22:48\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=4968s) >> I have a mechanical keyboard. Yes. >> Okay. >> So, now we're adding one to the left. Left. Okay. As left and surround. Okay. So, let's add this back. >> Now, when Visual Studio, you don't have to make a selection. If you just want to cut the whole line, you can just press Ctrl X with no selection. It will cut the whole line. >> Oh, really? >> Yeah. >> And Ctrl + C works the same way, but you should add it to the middle. [\[1:23:21\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5001s) Remember, >> more to the You should tap that line a bit. >> Well, actually if we move this move this guy. >> Yeah, but I want them people to see that there is an empty space there. >> Okay. >> And where's the one to the right? Oh, yeah. Now it is now. Okay. Because then I had to ask, hey, where's the one to the right? [\[1:23:55\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5035s) >> Okay. That's such a huge gap in the >> Yeah, exactly. I mean, I can see that there's above, below, and to the right. And that makes me wonder, maybe this is the one to the left. >> Yeah. >> Okay. Run all the tests. >> Okay, one failed. >> Let's go ahead and control D. All right, >> perfect. One to the left. Should do that. [\[1:24:26\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5066s) R. >> All right. Okay. >> Now, now it failed. >> Now we know where, now we've learned something. >> >> index outside the bounds of the array. >> There you go. >> Now we can go and fix I think it's the 19 thing, isn't it? >> you want to debug it or do you know where it's coming from? >> Yeah, let's debug it. [\[1:24:56\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5096s) This is probably this. >> But you have to debug from the test. Remember this, >> right? >> so it's better if you put the breakpoint in the test and not in the production because otherwise you're going to get there every time for each. >> Oh, so you were just going to run the whole test. I see. >> is this how you do it? >> This is the ReSharper [test runner](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_37 "The library, the assert, the runner, and the reporter (The Art of Unit Testing, 3rd ed., ch. 2)"). You can do it that way as well, but you have to put a break point somewhere. [\[1:25:28\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5128s) >> So, where is your your break point, >> right? >> It's right here. Okay. >> Remove it was at >> here. Add right. Right. Right there. Okay. Okay. >> Right. >> Okay. Then debug the debug that bastard. Right. Just do you is there a shortcut >> test with debugger? Well, we can make a shortcut if you want. [\[1:25:59\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5159s) >> Do that later. I just want to get this. [\[1:26:33\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5193s) X is zero when y is three. x is zero. Who's so we have an x which is a zero. cuz x - one is a zero. >> Wow. >> Mhm. >> Okay. So, do you understand the bug? >> A little bit though. The X react position though. How do we go? Is there a way? I'm not too familiar with [\[1:27:04\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5224s) Visual Studio Debugger. Is there a way to back out to history or do I have to rerun the test? Well, you can go you can see here in the call stack you can go to where you to the location of how we got here. >> So you can see that this is X. It was one. >> I see. >> Okay. >> Mhm. And then so maybe I can go even higher in the call stack. >> Mhm. So we had a one and a three because we had a two, [\[1:27:37\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5257s) >> right? >> So Okay. So our bug is that if we are if we we don't have to check anything that's lower than zero. That's our bug. Right. >> Right. >> Okay. >> Right. That's our bug. >> Right. Right. So how do we make this pretty? >> Well, we don't have to check remove surrounded stone. Yeah, we do have to check if we move around the stone, but only if x. [\[1:28:08\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5288s) Well, we for each of these ifs, we actually have to check if we are lower than zero or not. >> Right. >> Or we can also just you know what the simplest thing would be to just catch all the errors. Catch an index out of ringer. >> All right. That's interesting. But That's cool. [\[1:28:49\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5329s) I never seen it used that way, but that's very that's very cool. >> The the point here is to deliver, right? If ever this becomes a problem, because sometimes, you know, it's the performance thing, we can do something about it. But usually that's not a problem for go games at least where people think for hours. >> Okay, run all the tests. But alt R won't run. It will just repeat the last action. So you have to go to the project and run all the tests or just outside the test just run all the projects. [\[1:29:26\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5366s) >> So to run tests >> run all the tests. So you can click outside the test run test. Okay. >> Oh, still one fail. >> Interesting. >> Well, we had other failed other Yeah, there's not an out exception. >> Oh, okay. Talking myself. Let's see. >> Aha. So, it's it's not good enough. Mhm. >> So the the way I think about it is that we get an index out of range exception, [\[1:29:58\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5398s) But we still need to make it an empty position. So >> ah you're right. >> So we only we have for each of these ifs we actually have to check if x is I mean only for the ones where x is smaller than y than zero. For now we can just check smaller than zero and then we can check for all the others or you can just say is x yeah we basically have to do each if if check is it it's possible. [\[1:30:31\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5431s) Is there a way for an array to check if it's allowed to use a specific instance instead of checking if there is the size of x or y? I'm not aware of any. >> then I guess it would be here. Sorry. So here we would say if [\[1:31:01\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5461s) X is smaller than two actually it's bigger than one then one and right but that wouldn't work because then for each x where it's actually not bigger then we will always have a false here >> right >> aha so that's not good enough >> so we have to have a separate if for each one agreed [\[1:31:34\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5494s) >> at least for now so we can say if and my swamp stone color. This can we change it to an ore? I guess. [\[1:32:04\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5524s) >> No, that's not going to work. I think we might need a break we might need to break up the if statement. Yeah, just >> then >> Okay, so if x is bigger than one and y well if x is bigger than one then we can do all the checks for x is bigger than one. How's that? >> Right. >> H >> right. Yes. one then we can do [\[1:32:37\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5557s) What do you think if let's see x - one oh maybe we can just use it as flags right so we can say and equals matrix then surrounded on left [\[1:33:09\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5589s) Equals equals true. It's bigger than one. And then we can say else surrounded on left equals true. Right. >> Yes. So if x is on the left vertice then it's surrounded on the left. >> Right? >> We can make it nicer later, >> right? [\[1:33:41\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5621s) So you can do that for each of the sides, >> I guess. So what do you think? >> I I agree. You could take it out of the try statement, too, then. >> Sure. Let's get rid of the try. [\[1:34:12\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5652s) It would just be each of the positions in the end. So left surrounded and right surrounded and >> yep surrounded on left and surrounded on right on right and surrounded on top and surrounded on [\[1:34:42\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5682s) Bottom. Right. >> Yep. You need a parenthesis. So, yep. >> Okay. So I guess we know where we're heading. >> So, we need to repeat that. >> Yeah. You want to try it? I think it will be faster if you do it on your end. >> All right. >> And I think Yeah. And we also have to check for color white. So, that's true. Yeah. So, we And you know what? We could make this into a method later, but let's just make it all happen right here, >> right? [\[1:35:18\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5718s) >> Just duplicate, dude. You're copy pasting like crazy. >> You want me You want me to do a control D instead? >> Oh, next time. This is very out of habit. So this would be less than 90. [\[1:35:48\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5748s) This would be plus y is greater than one. >> You have to make it surrounded on the right also. >> Yeah. on this one. So let's try it on. >> We don't have to do the smaller than 19. Actually, we don't have any test for it anyway, >> right? [\[1:36:21\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5781s) So you want to just get rid of it then. [\[1:37:15\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5835s) Then you can just declare each one surround rounded on bottom is equals true but only if right if stone color basically you can just declare this right just change this surrounded on top equals >> right >> stone color matrix wait right wait Okay. [\[1:38:02\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5882s) What is this? Oh, >> maybe a try catch thing. Just remove one. still showing of course cuz we're not done yet. We're not done yet because let's see remove the stone. We have this for false surrounded on bottom. It cannot always be false. It has to be true at some point, right? [\[1:38:33\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5913s) We're missing another one. Just the last one. Crl + C. The only one we care about that we actually calculate for X is on the left. So it's on bottom if it's X + one. Actually, no, it's X and Y + one. And surround on top is X - one with Y. No see y minus one [\[1:39:09\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5949s) >> this is basically what we had >> right >> so we're only on right now if x is bigger than one >> we have >> we have true and else surrounded on left is true by default let's see At least we have to test to know. >> I think it this supposed to be a zero right there. Same thing with here. [\[1:39:42\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=5982s) >> Oh, okay. H never mind. It's dead. >> It's dead. Huh. Now, this is where source control would back up and we would just undo until we had that one failing test again. >> Yeah. >> Let's see. Okay. Let's try again. We have the surrounded one. Let's just do the whole thing here again. So, we can go back to where we had some kind of surrounded on left is x [\[1:40:16\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6016s) Minus one and y. And then we just just get rid of the whole thing. And this is almost where we were, right? Right. >> Alt R should have just one failing test. >> Right. But with the indic to empty position position is filled. Yeah, that's the index hand. Now we have to check just check this. [\[1:40:46\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6046s) So we can say surrounded on left equals x= z. >> Yeah. or >> or this is white. Let's see. All right. So, same thing with the >> same thing with the yus one surrounded on top. So, y equals z. >> So, because we still have index out other out of balance, right? [\[1:41:20\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6080s) >> Yeah. But it's not about the other things. You think it's the other things? I mean it's oh it's the same test but we have four failing tests. So is the to empty position other empty is that affect >> I think it's this part right here if you add the y equals z same thing that you did before. >> Sure. [\[1:41:55\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6115s) >> All right. Only one fail this time. left and surround that doesn't make sense because left would have worked. Empty position filled position. So it's either x is zero surrounded on right should be okay surround on bottom should be okay. So what the hell happened? >> So this one we can probably debug. >> Okay. >> But I need debug. So is this the same test that we're is failing? >> You just look at the name >> right [\[1:42:27\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6147s) >> you can see the name here Edstone left >> okay I'm just going to remove this. Okay. Which one is the same? Actually, I don't know if it's this one. [\[1:43:11\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6191s) So, it's supposed to say true, true, and then the bottom one, but still false. So, how is the bottom one still false? >> Well, it just returned false. So, let's do >> is our test wrong? X Y + 1 is stone color white. Interesting. So, the bottom is X and Y + one, right? If we go to the test, [\[1:43:42\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6222s) This is our test. We have this is the black stone. This is the right. This is the top. This is the bottom. >> Oh, this. No, actually not. >> H. Yeah, this is one. It should be on the left. It should be two. The test is wrong. You agree? >> No. Like because xus one. [\[1:44:14\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6254s) >> Oh, yeah. Oh, yeah. So sorry, my mistake. So it is one. Okay. And we're then we're checking the left of each and every one of them, but we're not checking the actual one. So maybe that's our bug, right? Cuz here we're checking for X and Y, but we're checking all around them, but we're not checking X and Y itself. >> Okay? >> We're not checking to the right of it. That's what I'm saying. We're not checking X + one. >> Oh. [\[1:44:45\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6285s) Oh, you're right. You're right. >> So, we're missing a check for x + one. let's go to control alt l for solution. Oh, nothing. Interesting. run all the tests. [\[1:45:22\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6322s) >> Nice. >> Okay, so we're getting there slowly but surely. >> All right. >> so we have a test for the left. >> We have a test for >> Go ahead and still add one for the right even >> we know it's going to pass. >> You You think it's going to pass? >> I think it's going to pass. >> Then let's make it fail first. Then we have we've added too much. >> Why do you think it's gonna it's gonna pass? >> Right. >> What assumption did we not add? >> It make something do generic. [\[1:45:54\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6354s) >> So this one we added in that did not affect the previous test. I did make the other test pass. So if I comment this one out and I add the right version, it'll first run all the tests. >> Okay. Right. Okay. Can we remove anything else by the way? Just to see what happens. Right. Okay. [\[1:46:27\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6387s) So, you can see I'm just checking our [coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)") a bit. See what happens. Okay. So, we definitely don't need the line there. >> Yeah. So, we need another test. True. Good. Good catch. Oops. How did that happen? Control D work with this. >> Yeah, it works with everything. Nice. [\[1:47:15\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6435s) To the paste. Oops. What did I just do? >> Yeah, you just push the line to the right. That's okay. Just >> Okay. >> See? >> Okay. Now add the one to the right. >> Fail. >> Okay. On on comment should pass. [\[1:47:47\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6467s) >> Should pass. Sweet. >> Okay. Okay. >> Okay. >> So, now we're getting somewhere, I guess. Let's see. So, now >> we got to refactor, right? >> We got to refactor. Well, remove stone at this place and that place and this place. What do we Here is where we just just extract another method and say control M remove [\[1:48:30\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6510s) Surrounded. Okay. Check stones around position and remove if needed. How's that? >> Yeah, I like I like the last part. >> Stone check. Stoned. Is anyone stoned around this position? >> and then we have, let's see, alt R just to make sure. [\[1:49:04\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6544s) Now, do we really need the position status matrix anyway? >> The pos >> I don't think so. We can just check if it's filled by getting the stone color. >> Well, the stone only has two values, right? Stone color matrix only has two values, right? >> Yeah, but it could be null. If it's null, you can just say that it's not filled, right? >> Oh, will it be null? It's a good thing to try then >> return [\[1:49:37\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6577s) So we can say if position status of control V is stone color matrix >> yeah we just have to replace the stone color matrix. Yeah. >> Return control shift space. Does it give me anything? Yeah. Position status empty. >> Right. >> Otherwise just return [\[1:50:16\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6616s) Position status. Control shift space. No. Return. Nope. Nothing. Return status filled. That's it. >> All right. Give it a try. >> Oh, why does it say that this will never get executed? Interesting. >> It's because I'm pretty sure in an array it >> treats the enum value zero. It sets it to zero and one of them is probably set to zero which is black. >> So we can make it the nullable type. >> Okay. [\[1:50:48\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6648s) >> Like this, right? >> Oh yeah, you write something something like that. Okay, there we go. Let's see. Empty position but but failed. Yeah, we just have to change the test, I guess. No, what happened? Let's see. Rar equal empty position status. What did I return? [\[1:51:19\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6679s) Failed. Stone color matrix. Is there anything? It's nullable. Ergo. Yeah, whatever. So, I'm guessing it returns field all the time. >> Let's see again. [\[1:51:49\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6709s) >> What was the error again? except empty but was failed. It's never null. We can just if this value I guess equals null. Oh no. The value can never be null. We can just say [\[1:52:21\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6741s) Is no I think no >> if I has value I think is the is >> yeah true I agree [\[1:53:00\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6780s) Interesting. So when you fill out an array with nullables, you still get non-nullables. Interesting. I guess we can just go back to where we were. I don't care about that. Let's see. Okay. We do control Y. Okay. Let's see. We back to where we were. Okay. [\[1:53:31\]](https://www.youtube.com/watch?v=8riX4rG7Idc&t=6811s) Okay. Let's see. I'm going to stop here. We're going to do another one. ## Related - [Replacing beforeEach() completely with factory methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2) · The Art of Unit Testing, 3rd ed., ch. 2 Book section on replacing beforeEach() with factory methods, the same choice the pair make over setup methods. - [Avoid setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162) · The Art of Unit Testing, 3rd ed., ch. 8 Book section on avoiding setup methods, backing the factory-method style used for the first board tests. - [Naming standards for unit tests](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html) · osherove.com Explains a unit of work and its three kinds of end results, which the pair discuss while naming the first test. - [TDD in .NET course - Day 2 Learnings](https://osherove.com/blog/2011/8/11/tdd-in-net-course-day-2-learnings.html) · osherove.com Course notes listing unit-of-work boundaries and TDD as removing assumptions one by one, as done in this session. - [How Do You Explain Pair Programming?](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html) · osherove.com A short list of pair programming benefits, useful context as the pair agree how they will pair. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19), ch. 1 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [Entry points and exit points](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18), ch. 1 - [Setting up and tearing down](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_171), ch. 9 - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 - [The library, the assert, the runner, and the reporter](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_37), ch. 2 #### The Art of Unit Testing, 2nd ed. - [First steps with NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3), ch. 2 - [More NUnit attributes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6), ch. 2 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 #### osherove.com - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) - [Pair Programming Q&A](https://osherove.com/blog/2003/9/9/pair-programming-qampa.html) - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) - [Test Coverage and testing angles](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html) #### artofunittesting.com - [Definition of a Unit Test](https://www.artofunittesting.com/definition-of-a-unit-test) [Next lesson Mapping Moves](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/mapping-moves/) --- title: "Mapping Moves" url: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/mapping-moves.md" canonical: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/mapping-moves/" tags: [] author: "Roy Osherove" description: "Lesson 2 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 30:05. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Mapping Moves 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD Pairing Sessions - Building a Go Game](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/) 3. The Sessions Lesson 2 of 11 Duration: 30:05 [Watch on YouTube](https://www.youtube.com/watch?v=LUjsx2dqCJM) ## In this lesson In session two Roy Osherove and Raymond Lim list the missing moves and features in an Excel file, with Raymond explaining the rules of Go. The list includes surrounding groups, invalid moves, switching turns, the winner, handicaps, board sizes, saving games and komi, which means there is never a tie. Aiming for a game that can be finished, they test that white wins by default because of komi, through a public who-wins method, since komi is internal. ## Transcript 3,657 words [\[00:03\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=3s) Hey, Raymond. >> Hello. >> Welcome back to session number two. All right. >> How does it feel so far? Feels good. So far, I think I'm getting the hand hang of it. Although, I'm look I'm looking forward to when we start doing the isolation of responsibilities, I think you call it. We split into multiple objects. Yeah, we can do the refactoring now. As long as everything still works. [\[00:34\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=34s) So, just to make sure, let's run all the tests again. If I press Alt R, everything should still run. >> Yes. Let's see. Eight passed. Zero fail right here at the bottom. Okay, that's good. Okay. So what I think we should do is first of all let's try to to put the production code and the test code on a sidebyside basis. So we'll see maybe if that will make things bit more readable. [\[01:08\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=68s) So to do that we can just use some of the ReSharper goodness. Let's see is that the we have the board here. If I press F6, you can just move it. >> How do you do it? >> Just press F6. >> F6. >> Okay. And again, ReSharper annoys us with this. Okay. Let's move to another file. [\[01:43\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=103s) >> Sounds port. Yes, sounds good. >> Okay. Okay, that's good. So now we get to put the game board here and the test on the other side. >> Cool. >> let's see. 100% should be okay. What do you think? >> I think it's okay. [\[02:15\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=135s) >> Okay. Yeah. Okay. I think we'll we'll just zoom it for the for the maybe viewers later. >> as long as we both can read this. That's the important part right now. >> Okay. >> Well, I have the code on GitHub anyways, right? >> Mhm. And and I'll definitely I'll add a link to that in the blog post. >> Okay. >> Okay. Oh, so just to make sure last time we we finished everything with just the the initial moves of understanding when something is being surrounded and then to automatically remove the piece. [\[02:47\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=167s) Right. >> Right. >> it's interesting. I already got some comments about the video where someone says you're like a child who's trying to learn the rules of the game. And it's better if maybe an expert in the game would explain the rules and then you can go ahead and and and and try to write a test for it. And I think some of it is because we're doing things very incrementally. And another point is that I I haven't played Go in a long long time. [\[03:18\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=198s) I think last time I played it, my grandmother bought me some ice cream actually. So that might have been a long time ago. And it so I think what would be cool is if you had opened the Excel file here, just put it in front of Visual Studio so we can see it and you'll explain maybe some of the possible moves so that we can choose which one to try to implement next. >> Okay. So, so far we have it. We're just surrounding a single stone. [\[03:48\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=228s) So, a couple of moves that we need to, test is one where we surround a group of size two at least, like multiple size greater than one, right? And we should probably do >> How would you name that? >> is there a name for this pattern? I don't think so. At least I'm not a expert. [\[04:20\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=260s) Go. >> Okay. Can you can you write on You can write just write to the right of it maybe just the name of this as yeah surround multiple maybe okay should I generalize it more? >> I think it's around group. Do you think it will be different if we had B and just B just below it like like this one for example? [\[04:53\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=293s) Ctrl + C. Wait, I didn't use control, did I? Ctrl Ctrl + V. We would have a B like that, >> right? >> Is that a different scenario, do you think? It depends on how we implement it. Yeah. But I mean it probably another test just to verify [\[05:24\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=324s) That we should verify, right? >> Okay. So let's just call it surround group. I think they're both surround group. They're just different >> different groups, right? >> Yeah, different groups. Oh, wow. I'm not sure how we that would work, but yeah. Okay. So, that's around group. >> Okay. >> Surround group. Okay. What else? >> we also need to have a test where it's like if there's a edge [\[06:00\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=360s) And then there's a stone. This this surround is also considered surrounding. So maybe call >> I think that actually works right now. We can try it. I'm not sure if it works. >> Okay. >> Sure. >> Yeah. >> and and over to the right maybe here. >> what other scenarios here do we have? So we also [\[06:33\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=393s) We also want to verify that invalid moves such as if there is opposing color stones that the user trying to place here is an invalid move. So >> So placing B is invalid. >> Yeah, placing B is invalid. >> Okay, so you can write that down maybe. Just as a sentence [\[07:19\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=439s) I mean in this case you would just say that B is invalid. Right. >> Right. >> And to me that's more readable. I mean you can just write it just below B is invalid. Okay. >> What else? >> But then >> Mhm. >> another But then a scenario where placing B is valid is if it removes an adjacent group, an adjacent stone. So here B would be valid because W would be gone. [\[07:50\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=470s) >> Ah, nice. >> Okay, that's good. strict way to strike this up. Maybe just make it red. >> Okay. So, so here B is valid actually. >> Yeah. [\[08:20\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=500s) Or should I specify which B? B1. I mean call it B1. Okay. >> D1 is valid. >> When surrounding when when when Yeah. When surrounding W maybe. >> Okay. >> What else? >> say again. I think that's good enough for now. [\[08:51\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=531s) >> But where where where where is your if if we if we had unlimited time, money, resources, what other moves do you want to implement? >> I think that's basically exhausts all the basic options. >> Are there non-basic options? Is there something more complicated? Well, I mean, no, I think it exhaust all the options like the like once you play a game, this should this should take care of everything. That's what I think, right? [\[09:22\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=562s) But stuff that we need to do is also need like verify switching turns and then afterwards counting the territories to see who's the winner and who's the loser. >> Okay. Why didn't you write that down? Determining winner. >> Yeah, determining winner. >> But when is the winner determined? >> so the end of the game is deter is when both players pass consecutively. [\[09:54\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=594s) So determining end of game. So that means a player has the option to place a stone or pass. So they have two actions, two options, right? >> Mhm. >> And what else is any other what about switching turns? You said, right? >> Yeah, switching turns. [\[10:25\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=625s) >> And what what would that mean? Would that mean that now only white is valid or only black? >> Right. >> Okay. Anything else? >> There there are no dice in this game, right? >> Say again. >> There's no dice in this game, right? >> No dice, >> right? >> No dice, Roy. Okay, >> so setting up the board like handicaps. >> What does handicaps mean? So when there are two unequal players, they have the option to play a handicap game where [\[11:00\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=660s) The weaker player places sets up the board by placing stones >> on the board such that they have an advantage so it's more equal game starting from the beginning. >> Okay. Is handicaps a sub requirement of setup board or it's a different requirement? >> It's a sub requirement. I guess we also need to reset the board or clean board. [\[11:32\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=692s) >> We also need with the handicaps the person who goes first is different. So deciding who goes first but by default the if there is no handicap is there a default? >> Yes. >> And that is >> black goes first. >> Okay. So no handicapped. Who? So deciding who goes first. Yeah, that's that's the one we just have above. Okay. What else? [\[12:06\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=726s) There's also multiple size boards. 9 by9, 13x3, 19 by 19. Okay. And I kind of also want to do because the game could be long. >> load saving the game and loading the game. >> Very nice. Okay. >> so determine a winner with a couple things. There's accounting territories [\[12:42\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=762s) Plus for how you say minus stones removed. So that means in the future we're going to have to keep track of how many stones are being moved. And also another part of the setup would be something they call komi which is part of the handicaps thing. which actually so if so basically white would have a set starts with a set number of points to to offset the handicap a little bit. [\[13:15\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=795s) I also think in the original game like where there's no handicaps, white has like 0.5 points so that there always is a winner. There's never is never equal when they finish the game. >> Okay. So we can decide that begin game with begin game with some points or something like that. That's what you mean, >> right? Right. >> Is that komi as well >> or is that komi as well? >> Yeah. >> So komi is what does that mean exactly? [\[13:48\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=828s) >> So not equality >> because black >> has advantage when they go first. White gets a little bit of a a little bit of a few points like 0.5 point. It also allows the game so to always have a winner. There's never a tie. >> Okay. So I you can say komi and then next to it just say u always have a winner. >> How's that? >> All right. [\[14:21\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=861s) Okay. What else? I think this is basically it for just making the game engine. >> Okay. What's switching here? Switching turns. Okay. >> Yeah. [\[14:53\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=893s) >> Easy for >> Okay. So let's just do this just so we can see Okay. So now this is much more interesting because now we can choose what to implement next right and based on that [\[15:25\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=925s) Our design can easily easily change. >> so this would be interesting because there is no right way but it kind of reminds me of do you know those books where you're you have a dilemma and then based on the solution you choose you go to a different page in the book. >> Mhm. I think it kind of feels that way to me right now >> because each one of these u goals will lead us down a different path of implementation because the design will change and the refactoring will change based on the order of how we do this. [\[15:59\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=959s) So there is no one way we can try and see where something leads us. So usually what I try to do in [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") is to implement things in the [simplest way](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") the next simplest thing. Okay. But there are a few simplest things here. For example, determining the winner is its own separate goal and it's it's it might be rather simple. I'm not sure. Or just determining the end of the game. So, I'm not sure. Is there anything specific you want to try first to implement? [\[16:33\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=993s) To me, the next simplest thing would to expand surrounding the groups. Another simple thing would probably be setting up the board because that's like totally tangent I feel to what to what we already have. >> but in a way setting up the board is just creating a new instance of the board, isn't it? >> Yeah. Yeah, exactly. >> So, is there really a need to set up the board? Is there something specific that we don't have in board setup? [\[17:05\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1025s) We don't right now we don't have the option to select a smaller size board. Right now we only have a 19 by9 board. >> Okay. >> another thing is we don't have handicaps to like to add the board before. >> Well handicaps to me feels really complicated because we need to figure out where to place stones so that someone has an advantage. >> Right. You're right. >> That might be actually one of the more difficult things. >> I see. But a simple board setup is just a clean board, right? [\[17:39\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1059s) >> Right. >> maybe board size. Okay, we could do that. But then that would mean that the default board size would be 19 >> if we don't want to break existing tests probably, but not not necessarily. Okay. you we can also start with komi that we always have a winner. By the way, we don't have any scoring right now anyway. Right. >> Right. Right. [\[18:10\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1090s) >> So maybe adding score to might be something to do. What do you think? >> I feel scoring though is basically >> Sorry, what? >> Scoring is basically decided at the end with like the territories. But you say that there is a komi where someone already has some points. >> Komi is just like a set just set at the beginning and then it only comes in to play at the end when you decide the points the total number of points. [\[18:42\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1122s) >> Okay. So there is nothing to do with points so far you think? >> Yeah I I don't know. I was thinking of adding tests for dealing with points at the end after setting up everything else. >> So that means that our demos will never have a winner or a loser until we finish the whole thing. >> Yeah. >> Would you be okay with that? Because I I think it would be nice to have a game where we can finish a game. It's just we would have less features less abilities during the game. [\[19:16\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1156s) Like we can have a game with a winner or loser but no but we can't detect group surroundings or something like that or liberties are not yet no liberties are still not a not a problem etc. >> and that way we can basically have a game from start to finish and then we just keep adding features to it. >> Interesting. Okay. >> So that might be just one way to look at it. We can go either way. [\[19:46\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1186s) We could also decide to do switching turns. >> Mhm. >> That might be simple to do, right? So that we know whose turn it is. So we can just say >> basically which which stone color is allowed etc. What do you think? >> Right. Right. >> Okay. So, [\[20:21\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1221s) So what do you think? It's your call. It's your game. You're the driver. You're the expert. >> Whatever you decide can ruin the whole thing or make it a great success. No pressure. >> I'm just kidding. What you said about the komi part, starting with a with a basically making a whole game. That sounds very interesting to me. I want to see how that turns out. Okay. So, we want to be able to finish a game. >> Mhm. >> Right. Okay. So, to finish a game, we need to be able to have turns, >> right? [\[20:53\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1253s) >> We need to be able to determine the winner or at least in a very simple way, >> Right. And we need to have players to be able to pass, right? >> Yes. >> Okay. So, this one this one and this one. >> Mhm. Do we also need the komi for that or to be able to finish the game? No. >> No, we don't. >> Okay. So, I'll mark these in red so we'll know what we're working on, >> right? >> Okay. So, which one of them do you want to do first? [\[21:24\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1284s) >> probably determining winner. Well, maybe we might we should do with the komi because right now if we determine winner, they're both going to be have zero points and that's a tie and original game doesn't have ties. Aha. So you're saying the simplest test for determining a winner is that there is always a winner. >> That means we need to have a komi, >> right? >> Okay. So let's implement that as well. Okay, [\[21:56\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1316s) Cool. So I think we have something to do now. >> Okay. >> do you want to save this file so we can also then add it later to the source control? >> Sure. [\[22:33\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1353s) Okay. >> Okay, cool. Hold on, hold on, hold on. And we're on. Okay. So, let's switch back to Visual Studio and we're going to work on, as we said, Well, that's not mine. That's yours. Sorry. >> so can you switch back to to the Visual Studio? >> Okay. >> Okay. So, let's start with a test, right? What's the simplest test you can you can think of for combing? [\[23:08\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1388s) You shrink the visual studio. >> That didn't work. Great. What if I just said few show the whole desktop for now? Okay, that's much better. Okay, that's Visual Studio for you. And now let's try again to single window. this one. [\[23:39\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1419s) Now, can I also optimize your environment a bit by removing this toolbar? >> Go for it. >> it's just standard. I think there's a text editor. Yeah. Okay. We have more room now. So where were we? We're trying to write the first test, right? And this time we want to determine a winner. [\[24:10\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1450s) >> Mhm. >> Okay. Do you want to write you want to start? >> All right. Well, so actually maybe the first one should probably be the komi because that way we and then determine the winner after that. That way we always have a winner. >> So the way I think about it, komi is not an enduser feature. It's it's a feature of the game, >> right? >> So, it's built into the game, >> the player doesn't care if there is a komi or not. [\[24:41\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1481s) He just cares if there's a winner. I mean, in terms of engine, >> I mean, the way I think about it is that if you start a game and there are no moves, we we already have a winner. >> That is what komi is, right? >> Yes, I guess. Yeah. So in terms of the [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") here, the unit of work there is nothing called komi because komi is something internal. >> Okay. >> The the unit of work is probably some public method called who wins or something like that. [\[25:13\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1513s) >> I see. >> Okay. Does that make sense? >> I see. Makes sense. >> Okay. Oops. Okay. Where snar no moves >> or by default? >> By default you just shift tab if you want. >> All right. [\[25:48\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1548s) Expected behavior. >> Well, who who's the default? White. Yes, >> you don't have to say it's default winner because winner because it's it is by default. >> Perfect. Okay, that is the komi feature I guess right. >> Yes. So maybe if we would say by default or by default with komi it's white or something. [\[26:21\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1581s) What do you think? >> By default with komi enabled. What do you think? >> Say >> with by default or because of komi. >> What do you think? >> Like like this? >> Yeah. What do you think? I'm trying to to put the komi word in here so that people know that it it relates to that feature, >> but I'm not >> I think it's I think it's more clear. So, I I agree with it. >> Okay. So, Okay, let's do it. [\[26:54\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1614s) >> Oops. >> All right. So, >> by the way, hold on. You see how ReSharper hates this name? >> So, alt enter. Inspection options for inconsistent naming and then you say shut up. That's it. >> All right. >> Okay. All right. So, interesting part is how do we want to [\[27:25\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1645s) Do this? Oops. We already have stone color, right? So, we can just use that. What do you think? >> I agree. So will we have it border done? >> I would rather have a result and then say say see where we get the result from. >> Right. Right. I remember that. Okay. [\[28:06\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1686s) All right. So we can either have a board determine the winner itself or we have an object that looks at the board and determines the winner. >> Well, for now our point is to get something working to get feedback. So the simplest thing then we can refactor it. Okay. [\[28:54\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1734s) >> Okay. Then let's make it compile and see it fail. By the way, is there a possible result where there is a winner when there is no winner? >> No. >> Never. >> You should. >> I haven't heard of one. >> Okay. >> Okay. Just make it compile and so generate the method etc. >> What's the alt enter? It's always alt enter, dude. >> Alt enter should be burned into your mind. [\[29:41\]](https://www.youtube.com/watch?v=LUjsx2dqCJM&t=1781s) >> Oh, well, it should fail first. >> Oh, it fail. Okay. >> Okay. Alt R. Run all the tests. Let's see what happens. Okay. Failed. Now you can you can close this window with shift escape. this escape. >> Yeah, it closes tool windows. >> Nice. >> Okay, now let's make it pass. Simplest way possible. ## Related - [Avoid testing private or protected methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_160) · The Art of Unit Testing, 3rd ed., ch. 8 Book section on avoiding testing private methods, matching the choice to test komi through the public who-wins method. - [Overcoming the encapsulation problem](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6) · The Art of Unit Testing, 2nd ed., ch. 3 Book section on overcoming the encapsulation problem, relevant when komi is internal but must be verified. - [Entry points and exit points](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18) · The Art of Unit Testing, 3rd ed., ch. 1 Book section on entry points and exit points, the idea behind driving the komi rule through a public method. - [Test Naming Conventions With Unit of Work](https://osherove.com/blog/2012/5/15/test-naming-conventions-with-unit-of-work.html) · osherove.com Names tests after the public method that starts the unit of work, like the who-wins test written here. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 #### osherove.com - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) [Previous lesson Understanding the Problem](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/understanding-the-problem/) [Next lesson Stoned and Board](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/stoned-and-board/) --- title: "Stoned and Board" url: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/stoned-and-board.md" canonical: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/stoned-and-board/" tags: [] author: "Roy Osherove" description: "Lesson 3 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 30:14. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Stoned and Board 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD Pairing Sessions - Building a Go Game](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/) 3. The Sessions Lesson 3 of 11 Duration: 30:14 [Watch on YouTube](https://www.youtube.com/watch?v=AIcaF7KahL0) ## In this lesson The pair look for the [simplest test](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") that proves black can win, and the Excel file explains scoring: points for territory, a point lost per removed stone. They consider an event log for calculating the score, but choose a test that adds stones so black owns at least one cell. The laziest code, where the last stone added wins, passes, so a new test has white play last while black still wins. ## Transcript 3,414 words [\[00:09\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=9s) Oh, well, it should fail first. >> Oh, fail. Okay. >> Okay. Alt R. Run all the tests. Let's see what happens. Okay. Failed. >> Now you can you can close this window with shift escape. This >> shift escape. >> Yeah, it closes tool windows. >> Nice. >> Okay. Okay, now let's make it pass. [Simplest way possible](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)"). [\[00:40\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=40s) Okay, awesome. Obviously, that's good enough. We can move on, right? >> Right. >> No. What? >> No. >> I mean, would you leave the code this way, dude? >> no. >> No. Okay. I mean, it works assuming assumptions, right? The assumption we're making right now is that there are no moves, right? So, now we have to break that assumption. We can we need to say you can't assume there were no moves. [\[01:13\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=73s) White will not always be the winner, right? >> Mhm. Great. >> So, now we have to basically say we have to prove that it's a bug that it always returns white. So now we have to make the simplest test that proves that there can be a black winner. >> Okay. >> Mhm. >> so how would you do that? >> the simplest way there's two ways. One is making a territory for black. [\[01:45\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=105s) I think the other simplest way would be to remove a white stone like pretend it's captured and then basically that would be a minus one point for white. So, so I'm trying to understand can you put the Excel file again and and explain that to me? >> Okay. So if [\[02:16\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=136s) One scenario would be basically if the komi for white is 0.5 >> but then white stones remove equals one. Then the white points the score for white equals0.5 where black would be [\[02:53\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=173s) Black to remove is always zero. Well, if we set it up for where we just remove one white stone, but we did not remove any black stone. >> No, but somewhere in the middle of the game, I remove a black stone. >> It's still zero for the black. >> No. Yeah. I mean, if >> So, this is all just for the initial move. >> Yeah, that's what I meant. Just to get just to get black to be the winner. >> Initial points, right? That's what it this means. Well, we there's no real initial move like I mean to the the way a player can actually make this happen is surrounding a white stone. [\[03:38\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=218s) The scenario would be black like if there's a white then when there's a black that's how we get how >> so the only way to get any points is to surround someone and the only way to lose point to lose points is to be surrounded that's the only way >> you don't get points >> the other way is the amount of territories but that is calculated at the end of the game >> right So the the territories would be for black would be one. [\[04:09\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=249s) So it's also >> so I'm just trying to understand because this is interesting. This would be one black territory. >> Well, it's actually a little bit more complicated than that because of the the boundaries. If there was boundaries then the sides would be I mean if we consider it more like there's a white stone outside the boundary. >> Yeah. Then only only inside here would be black territory and that would be 1 one. [\[04:42\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=282s) >> Might be easier if I >> draw a boundary >> because what I'm trying to say is that we can we can write this test this initial test from three different angles. Right. >> Right. We can have a test that says white we can have a test that says black surrounds white, >> right? >> And then black is the winner. [\[05:13\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=313s) We can have another test. We probably need to have each one of them anyway, right? >> Another test that says white stone removed. Can we just have a test that says white stone removed and not black stone surrounded? >> I mean, you don't do you get positive points or do you always get just negative points? That's what I'm saying. >> So, the positive points is so the basic example would be if I had black at this corner and like let's say there's white stones outside. [\[05:48\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=348s) This right here would be considered a black would be part of black. >> Okay. So just let's Yeah. No, that would be a black like this actually. >> Yeah, right. >> And is there a white territory here somewhere? >> Sean, >> is there white territory as well here? >> Well, no, because there's no established boundaries. But actually, maybe a better one then would be white. [\[06:18\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=378s) White. So this is white and then everything else is neutral. So let's make this gray. Oh, that's not very good color. Let's call it green. What's a neutral color? Ah, that's a neutral color. Okay, that would be neutral. This would be white. Let's give it What's >> Just use white. It makes sense. >> All right. If that makes sense. [\[06:49\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=409s) So, this would be white. >> Mhm. So this would be a one point for white, one point for black. >> So there is a way to get the positive points. Okay. So now just to make sure we have ways to get points and lose points. >> So point plus point plus point for each [\[07:21\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=441s) Established >> territory. >> Territory. Okay. Oh, of course I said plus. I said equals. Plus equals. Great. >> no. I didn't like the pluses. Add points. >> Okay. And >> minus point for each remove stone. [\[07:52\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=472s) >> Minus point for surrounded and removed stone. >> That's it. >> Yep. >> Yeah. >> Okay. So, which one do you want to do? >> maybe the easiest one would be I don't know. They both seem pretty one. Well, the the removing a stone one, the easy one would be we just remove one. [\[08:24\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=504s) Pretend the user had removed one without actually setting up the board and interacting with the board. >> How do you remove one? >> If we just say board remove stone, a white stone somewhere, then we can say think we just minus one white stone. And then we just calculate the score from that. >> Is that a valid test? That's what I was wondering. >> so, so write the test to show me. [\[08:55\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=535s) >> So I just saying >> no, just write the test in the code. I mean, >> okay. >> So he does bring in interesting parts cuz I think what you're trying to do is to say, let's not actually do the moves. Let's just tell the board what happened. Right. Right. So, determine winner [\[09:34\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=574s) One remove white stone. Zero remove black stone. Effective behavior Black. >> Black wins. >> Yeah. >> Can just say black wins. Yep. >> Yeah. Okay. >> Okay. So, search equal [\[10:53\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=653s) >> but you know we already do remove stones from position right >> did we >> we already implemented that >> we just do we just don't have a public method for it >> because you can't remove a stone for position everything is just built into the board right now, >> right? >> Okay. >> Mhm. So maybe the best way would be without introducing another public method, the best way would be [\[11:24\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=684s) Actually just creating territories then. >> Well, you can create a situation where a stone will be removed. >> Yeah. Right. Right. >> Right. We can't do that, right? >> however, you know what I'm thinking now is that it would be cool if we had a class that we could just say points calculator or something like that. >> Mhm. >> Or board point calculator [\[11:57\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=717s) Where we would say stone removed from. So we could just basically tell it the play by plays. >> Okay. >> Because then what happens is that you can actually simulate the moves without actually doing them, right? >> Mhm. >> So for example, you can say territories one for black three. See what I mean? [\[12:28\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=748s) So we have >> so so I so what I'm saying is that it would be cool to be able to do this for example board dot calculator or you know what we can just say zen log then we would say stone Stone removed [\[13:07\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=787s) Stone color white. Mhm. >> Okay. Now, the event log is basically just an event log of what happened. You don't have to actually do it. >> Mhm. Okay. Wow. >> And the event log can be used to calculate the score. That's that would be a way to do it. And then you can just say, you know what, we don't need a board. We just need an event log to calculate the current score. >> Okay. Okay. [\[13:37\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=817s) >> What do you think? >> It's just a thought, of course. Could be horribly wrong, but let's go with it. >> what else? There are other ways to think about it. We can we can actually say board something got removed. But that would be too much responsibility for the board. I think it's not simple. I'm trying to just think if this is simple or not. [\[14:11\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=851s) So you want to just create maybe a territory. I don't know if that will be readable, but we still have to start with something. So I'm kind of you know I'm kind of in between here because in a way what I'd like to do is I'd like to simulate in the test I mean we have two we have two layers where we can test it. We have the actual game layer where we simulate a game as if it was played >> right? So you can say the game was played this way and everything should have been already calculated somehow and the winner would have been black. [\[14:47\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=887s) >> Yep. >> Okay. Which is kind of what we did up until now where we would say the position status would have been calculated etc. Right. >> Mhm. Right. And then instead of having an event log, we would just say board dot add stone to position like >> one and one or actually one and two and the the stone color. >> Mhm. Actually >> the colors first. [\[15:23\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=923s) >> Yeah. Stone color. White to one and two and to one to to one. Okay. So that would be somewhere like that. All right. But we want to make it black because we're trying to get a black winner, right? [\[15:55\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=955s) >> Sure. >> And also going to F2. [\[16:28\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=988s) Just going to try to make it a bit shorter. >> Okay. And then we would have a winner of black as well. Yep. >> What do you think? >> Yes. >> I agree. [\[17:10\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1030s) Nope. Shift space. Nope, that's not it. This >> Mhm. >> Yeah. >> Okay. So to me, this feels more like a real game where we can do an end to end almost test of the engine. >> Say this is what a winner. This is the simplest example of a winner. [\[17:45\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1065s) >> Yeah. >> And it feels less like cheating. I don't know. I mean, I think that definitely maybe towards later we will have our test will become much more complicated and we will have to resort to like event logs type ways of what actually happened, >> right? But right now, I mean, this this looks much much simpler to me, >> right? >> And then later, I mean, after that, we can refactor to an event log or whatever we want. [\[18:16\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1096s) >> What do you think? >> I agree. I agree. >> Okay. >> This does definitely feel less like cheating. >> Okay. And it's important that sometimes you also disagree with me. Okay. >> You can't just agree with me all the time. Do you agree? >> Gotcha. Okay. I agree. >> Okay. Okay. Alt R. Let's see what happens. >> So, we should probably rename the test. >> [\[18:46\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1126s) Determine a winner by default because of komi. Determine winner. One removed white stone. Yeah, I agree. I agreed. One do we call it a territory or one stone? one one cube maybe. How do you call one of the cells? >> Let's let's call it >> what about this >> black black only territories? >> Yeah, but territory is too long to write in a [test name](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html "Naming standards for unit tests (osherove.com)"). [\[19:17\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1157s) >> See one cell, one for black. The thing is >> Yeah. >> because there are other the rest of the board and there's no white stones. the the rest of the board is considered owned by black. Do you know what I mean? Like going back to the Excel sheet-c if there because so if there was no white stones right here >> Mhm. [\[19:47\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1187s) >> everything would be considered part of black. Oops. Hold on. Hold on. I have to clean my disc. >> Okay. So, you were saying >> Okay. So, I was saying if there was no white stones available, it would all these would be considered [\[20:18\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1218s) Black. So, all the black would be considered black territories. >> And when would they not be considered black? So, if I put in a white stone in here, let's make this white. >> All these because there's no determined winner of these territories. They would all be neutral. >> Yeah, but it they're both the black is a winner either way, right? >> Yeah, black is a winner either way. >> So, that's just another scenario, [\[20:49\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1249s) >> right? So we can add that to unetermined versus well undetermined versus default to a color areas. What do you think? undetermined versus determined might be better or just name undetermined terms. >> But well there is one there is [\[21:22\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1282s) One versus neutral. >> Yeah. >> Versus defaults to a color. How's that? >> I'm not sure what you mean by defaults to a color. >> as you said, if there is no white, everything else defaults to black. Right? Because black owns owns the other black basically won the rest of the territory because if you look at it in the other way, black surrounded everything else. [\[21:52\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1312s) >> Uhhuh. So so Uhhuh. Okay, I understand. So surrounding we can say that surrounding can go from either side cuz I think that's just another >> scenario here actually >> right >> so we would say surround from outer [\[22:22\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1342s) Side as well >> so we would have an edge an edge. An edge and we have like a black and a black and one something like that. >> Right. >> Okay. >> But that's we're not there yet. [\[22:54\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1374s) >> Right. You're thinking too much about the future. What did I just do? Okay. >> Well, the thing the reason I mentioned it was because for your for your naming of the game, you said one cell one for black. That's why I was a little hesitant about >> Okay. >> the naming. >> determine winner. So, how do would you describe that scenario? >> black black territories. Maybe >> what if we said at least one cell? [\[23:28\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1408s) >> That that's that's fine. That's fine. At least one cell. Yeah, >> because then it doesn't break the future. >> Yeah. >> Okay, cool. >> so now let's make it pass in the simplest way possible. Let's just make sure we're still there, right? >> Okay. Expect black, but was white. Awesome. How do we make this pass in the simplest way? [\[23:58\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1438s) >> That's what I was wondering too. >> Well, we can basically say that if I was the world's laziest developer, I would just say that whoever added the stone last is the winner because that's the only place we check. >> That would be the laziest implementation. Yes, >> probably the most incorrect, but yeah, >> it's not incorrect if the test passes, my friend. >> And if it's incorrect, you just have to prove it. [\[24:28\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1468s) >> All right. >> where is the ad stone? Where is it? >> Right there. >> Okay. So, when I say simple, I usually mean at the beginning of the method is always simpler than down later in the method because you don't have to go through logic to do it. >> Mhm. And you don't have and and if it's indented it's less it's more complicated than if it's not indented. So it's inside ifs or loops it's more complicated than without. >> Right? >> Okay. So the way I would say it is that I would just say [\[25:02\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1502s) Current winner equals stone color. I'm going to just say alt enter create a field and >> default it as white. >> Yep. I will return current winner. [\[25:43\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1543s) Still color white. Alt R. Yep. Congratulations. We have a feature. It's a boy. You don't like it, do something. >> So, in would you suggest we write another test to prove that wrong in order to refactor it? >> Well, we can have a Yeah, basically we have to prove well. Well, the first rule of [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") is you don't write a line of production code without a failing test, >> right? >> You we don't have a failing test. [\[26:13\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1573s) If you want to change it, you have to have something failing. >> Okay. But everything is already passing. So you you can write a new test if you want. >> What do you think? >> I think we basically have the same test. >> Okay. >> But add Well, we could actually take the same test. Yeah, we can do it as a test case. >> We would you want to do a different test case or same test case? >> We can do a test case attribute on the current test. [\[26:45\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1605s) >> Test case attribute. Have you have you used it? >> Oh, you Yes, I know what you're talking about. So, instead of making it add black stones, we make it add white stones. >> Exactly. >> No, that's >> Yeah. Yeah. >> But that that's not going to make it fail because it the expected winner is going to be white. The expected winner is going to be white. And well, let's see because I'm not sure. I think it will fail. >> Okay. [\[27:19\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1639s) >> It will fail if we have Yeah. Yeah. I I agree. It will fail based on it will it will pass because it's based on the last ad stone. So if we make the last ad stone black, but the winner will be white, >> the test should fail. Right. >> Right. So, I was saying that in order to make this test fail >> Mhm. >> and we just add add stone white in some random position. Or actually, you could even have the black in the black territory area. [\[27:50\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1670s) Actually, no, that's not right. >> All we need is that the black should be winning, but white plays last. >> Black should still win. That's all we're saying right now. >> Yeah. So, basically, white places a stone anywhere outside of that corner. >> Exactly. [\[28:27\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1707s) Stone color white to four. Yeah, >> we can also do three, right? >> Yeah. >> Okay. I don't want to go like crazy. Just just below it because it's important that there are no questions about the [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)") of this. So someone say why is it 17 or something, >> right? >> Okay. Okay. So black should still win. Let's see. Alt R. [\[28:59\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1739s) Okay. So now let's see what we can do. It's not just the latest. We actually have to start keeping score right now. Right. >> Right. >> Okay. >> Count territories. Right. >> Okay. Simplest calculations, simplest everything that will make everything pass. You want to try? >> All right. >> Just imagine you're the laziest developer in the world. You have to go home five minutes. What do you do? Just make as long as you can make everything pass. [\[29:36\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1776s) All right. Gosh. Well, the simplest would be to to check if this position right here is surrounded and what color it's surrounded by. >> Cool. Yeah, that would be cool. I like it. >> Okay. [\[30:08\]](https://www.youtube.com/watch?v=AIcaF7KahL0&t=1808s) Don't you just return whatever the color is returned from that position? The positions next to it and above it, right? ## Related - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) · osherove.com Four questions for finding the simplest thing that could possibly work, as the pair pick the laziest passing code. - [Measuring Simplicity in TDD](https://osherove.com/blog/2011/1/20/measuring-simplicity-in-tdd.html) · osherove.com Discusses priorities for code changes driven by a failing test, the step from the lazy last-stone rule to real logic. - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27) · The Art of Unit Testing, 3rd ed., ch. 1 Book section on test-driven development, the test-first loop of simple test, lazy code and a new forcing test shown here. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 #### osherove.com - [Naming standards for unit tests](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html) [Previous lesson Mapping Moves](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/mapping-moves/) [Next lesson Colors and Winners](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/colors-and-winners/) --- title: "Colors and Winners" url: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/colors-and-winners.md" canonical: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/colors-and-winners/" tags: [] author: "Roy Osherove" description: "Lesson 4 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 48:10. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Colors and Winners 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD Pairing Sessions - Building a Go Game](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/) 3. The Sessions Lesson 4 of 11 Duration: 48:10 [Watch on YouTube](https://www.youtube.com/watch?v=cIi9iyJXyrg) ## In this lesson The pair check whether a cell is fully surrounded by a color passed as a parameter, and add an empty color as the enum default because a new matrix is all black. A komi mode flag, off once a stone is played, keeps the default test passing, and logic moves into a new rules class. A broken large refactoring is undone and redone in smaller steps, and the board forwards get winner to the rules, explained with the Law of Demeter. ## Transcript 4,901 words [\[00:05\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=5s) You can just say yeah basically that's yeah >> I'll just rename it later. So, is there a way to check it's surrounded in the easiest way? [\[00:38\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=38s) If if there are positions in one two and so surrounded equals position stat matrix one two equals n Right? So that would determine if there are stones there. [\[01:10\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=70s) And then we also want to verify if the they're the same, too. That doesn't seem simple, actually. >> I think we're Yeah, I think we're we're too deep. Here's how here's an example how to simp simplify. Okay. >> Okay. >> what if we just did the whole thing here? [\[01:41\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=101s) This thing. Okay. Extract into a variable. Control alt v fully surrounded. Okay. Then the whole thing here you would extract [\[02:20\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=140s) I can just check if it's fully surrounded. >> Nice. is fully surrounded. Was it the one and one? You're >> right. >> And then you can just say if is fully surrounded just return whatever the color is. >> Color next to it. >> Sorry. >> Right. A color next to it. The >> color next to it. Oh yeah. There's no color there. >> Sure. [\[02:51\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=171s) >> But I can tell already that probably still going to fail because of the white part. It's not surrounded by white. >> Ah, interesting. So, we don't have any scenarios where black is the surrounder, >> right? We basic we left that out because we wanted to try that, >> but it wouldn't fail. Oh, it fails because if it's the color white. Okay, interesting. So I guess we have to go back and say okay we have to have a scenario of the black or we can have the opposite test. [\[03:27\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=207s) How's that? >> Well the the point of that test originally was to make it so that black passes. >> Sure. >> Okay. Because if we do it the way right now, if we change it to white, the original implementation we had before this would still make it pass. >> Okay. Okay. So, this is test is currently going to fail. And what we're going to do now, we're just going to make we're going to make another test that to get rid of this white thing here to get rid of this assumption. [\[04:02\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=242s) How's that? Or the other if we really want to make it pass right now, we can just copy it. Copy that method and replace the replace the white with black and use that method for here for now. Another way would be to So if I did this Oh, we can just check. Oh, hold on. Something even simpler. just pass in the color. [\[04:35\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=275s) >> Yeah. Yeah. >> As a parameter. >> Yeah. That that that that would work. >> So we can be so we can say control alt extract parameter place for occurrences surrounding stone color. ah surrounding stone color [\[05:08\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=308s) Surrounded by so and then I would say say it's really surrounded by and then you can say surrounded it's really surrounded by stone color black >> very cool >> let's See? Well, we haven't fixed it yet. We're just checking, but we're not using the color. >> Yeah, we did return the color, right? [\[05:45\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=345s) >> Color. Do we actually need to check? >> Yeah, we need to check and then return if surrounded so that the other tests will pass. >> True. That's true. So if surrounded, >> you can put the sorry >> if surrounded and then I'll put the return stone color matrix one two inside there. [\[06:16\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=376s) >> Yeah, but just return color one is just return color one >> and that's it. This one, the bottom one, you might want to >> Oh, yeah. >> re turn >> current. >> I don't think it's Yeah, I think maybe back to the It's just default stone white. [\[06:52\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=412s) Oh, it's so current winner. Oh, so white was black. >> Are we expecting white? Oh, it's a different test actually. >> Oh, I understand why. >> by default because >> Yeah. >> Well, actually, no. Oh, because fully surrounded doesn't check if if they're actually stones. [\[07:22\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=442s) So in our by default the surround the stone matrix is all white. So when you do this it's going to say it's going to return true because everything here is white. I don't know if that makes sense. >> Hello. >> Yeah, I'm trying to understand what you just said. Oh, so the stone color matrix if you break into this >> Yeah. >> every everything is going to be white or black. [\[07:52\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=472s) >> Okay. >> But is is black. So we need to have it also needs to check that the it's filled position is filled. So I could type [\[08:33\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=513s) Oh, we could just check it directly in the winner, don't we? One. So I'm talking about we need to do that. We need to check it's filled and it's the correct color. So we need to do that for for each of them. But I'm not What do you mean by it's if it's the winner? >> You need to Okay. So I think I understand. Finally. Is So maybe we're getting too deep. [\[09:04\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=544s) Do you think we could could have solved it a different way? Or are we jumping the gun a bit? >> Are we jumping the gun a bit? I don't think it's too deep. >> Mhm. >> surround kind of >> kind of corrects the >> the definition of it's fully surrounded by >> because >> the >> because they have the stone color but not doesn't say it's filled or not. >> But we just have to check for X and Y if they're filled just once. [\[09:35\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=575s) We don't have to check for each one. It's only surrounded if it's filled. >> So we can just check just once, right? Because if it's false, we can just return false, >> right? So we can say >> if not position status matrix X and Y. Actually, we don't have to check the position stat. We can just say the color status matrix, [\[10:09\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=609s) Right? >> No, I was talking about >> you you want to check if the stone that's being surrounded is actually have has a stone in there, right? No, I want to check that this the ones being the So I want to check that if there is actually stones surrounding it because right now it is right now when by default the array is just all black. So all we're doing right now is just checking if this is black, this is black, this is black, this is black. [\[10:43\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=643s) But it could be that these there's actually nothing. Why are they all black? That's what I don't understand. >> Because when we initialize the matrix >> Yeah. >> by default it's all black. It's not all null like you >> is that is that the default? Are you sure? >> I'm pretty sure we can we can run it through debugger and I'm pretty sure that that's that's what's happening. Okay. So, we still have to check for a failed position. [\[11:13\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=673s) Okay. not a color. >> Yeah. >> Okay. But so what I'm saying hold on hold on is what I'm trying to say is that if not what is it position status metrics >> x and y position status [\[11:44\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=704s) Filled just return false. >> That's it. >> I think that would make the other tests automatically fail because for the black territories this will be false. This will be empty position. So this would automatically return false and you will automatically return the current window surrounded would automatically be false. >> Okay. And what did you want to check? You wanted to check you want to check for each one also this the position status. [\[12:17\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=737s) >> Yeah. So it basically would be this. >> Yeah, I understand. >> But like the filled on left, filled on right, filled on bottom, filled on top. >> Yeah, I understand now because just the fact that it has a color doesn't mean it's filled. >> Right. Right. You But you said it better than I did. >> Uhhuh. I understand. Maybe we just have to have a default color that's empty instead. Then >> we can do that. >> And then we don't need the position status at all. >> Yep. [\[12:48\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=768s) >> That would that would be that would be a good way to eliminate one matrix. >> let's see. So we can go to stone color. >> Am I missing it? >> No, it's on the right side. >> Oh, yeah. >> It's not on the right. Oh, we did. We didn't move it. Oh, that's why. Just move it here. [\[13:18\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=798s) We'll move it later. Okay. Color black, white, color, >> empty. And when we initialized it, we just wanted to say that it was >> Where did we initialize it? >> we initialize it right here. It's it's an array. >> So we need to have empty as the default. >> Yeah. So you can set it as zero. You can make the enum int and set that zero. [\[13:52\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=832s) >> Okay. Interesting. So, let's run the test. You think that's the that was the whole point, >> right? But, for the fully surrounded, it's going to say it's going to say true anyways because of the because they're all empty. So, it's going to say surrounded by empty. >> But, we did add things to the position. >> Say again. [\[14:23\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=863s) But we did add positions to the board. They're not all empty. >> I see. >> Right. We added two stones here. >> I'm talking about the the komi test because one of the tests that was failing was the one where we did not add anything. >> so which one is failing right now? Let's see. Determined by default because of komi. Okay. So this test is actually passing. >> Yes. >> But but because of komi it's not. Mhm. >> Uhhuh. [\[14:53\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=893s) >> Because of >> So we can Okay. So in that case, we can just decide if we're in komi mode or not, right? >> Okay. Yeah. Yeah. That would be the simplest [simplest way](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") to determine that. >> So here's the way I'm thinking about it. Komi can be just a simple flag. Once someone is played, we're not in komi mode anymore, >> right? So basically if in komi mode then what do we do? [\[15:24\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=924s) Return true. >> I think the simplest would be would to put that into get winner and then set komi mode in in add stone. >> Okay. So get winner right if in komi mode return. Come on stone color white. That's all. [\[15:55\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=955s) >> Right. >> And just equals true. And >> it would be set to false. Add stone. >> Sorry, >> it would be set to false. >> Add stone. Exactly. So, add stone in mode equals false. Let's see. [\[16:27\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=987s) Okay, 11 passed. Yay. You see how simple that was? Oh god. Go is not a simple game. Actually I think we can get rid of some of this stuff actually. >> Okay, >> I'm pretty sure. >> because do we need a current winner? >> I'm trying to understand >> what do we do then? What do we do here? >> If it's well actually we don't have a test to make that part fail. [\[17:01\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1021s) So until I think if we remove the current winner part we the test will still pass. Okay. So we have komi mode and let's see can we start to refactor some of it now? What do you think? >> Yeah. >> You want to separate some concerns here? >> [Single responsibility principle](https://osherove.com/blog/2013/3/6/refactoring-string-calculator-with-solid-principles-in-mind.html "Refactoring String Calculator with SOLID Principles in Mind - Examples Needed (osherove.com)") etc. >> Oh okay. Yeah. >> What do you think? [\[17:37\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1057s) >> Yeah, I think we should do it. >> Okay. What do you want? How do you want to refactor it? >> I was thinking that maybe the board should not be the one that determines if a stone is surrounded or not. Okay. >> Or is that is that to >> No, we can try to do that. Sure. So, you want to check if so how would where how would you do it? [\[18:10\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1090s) >> So, you would pass it to an object that would you you pass the board to an object that that does the calculation that does the that that does the checks. >> Mhm. Okay. So for example you might say you create a class here class rules maybe. [\[18:41\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1121s) >> Yeah. And we might have like a public board. [\[19:22\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1162s) Board just even a field like that. >> and then we can say check if stone around position is or removed if needed. We can just move that with function FF6. See again or control shift R. Extract members convert [\[19:53\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1193s) Extract class from parameters. Pretty sure we could have moved that. What if we made it public? So we can move that. Alt enter. Now we can see if we can move that yeah but basically we can say public check class if needed remove surrounded stone [\[20:24\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1224s) And then the whole position status matrix well it changes the position status matrix of the current board. Right. Right. >> But then we can just say empty position just refactors this whole thing to say control alt m empty [\[21:03\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1263s) And then we can say just take this whole thing and just of course surrounded by where is that fully rounded by we would get the [\[21:38\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1298s) We refactor this into a method of m get stone color basically. >> Mhm. >> Make that here x again. No, I mean I used using command access. [\[22:25\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1345s) Just the whole thing like board get stone color. He didn't make it public yet. Get stone color. Ah, this is not fun. That's life, right? Alt enter. Make it public. Same thing here, right? So, we could just do [\[23:27\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1407s) Okay. And board bank position empty. Let's see if there's anything else we missed. is fully surrounded. Actually we need to say rule right >> is fully surrounded by let's enter [\[23:59\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1439s) We might want to make it public but we also want to make it into a field. So now we have a like a private space. >> Cool. >> Almost there. >> Yep. >> Rules. [\[24:36\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1476s) Just need to initialize it. >> Mhm. So, I'm going to use ReSharper for that. Alt insert. Pretty sure there is an insert here. Is that an insert? Nope, that's not an insert. Press alt insert on your computer. Okay. Constructor and then we will choose rules. [\[25:08\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1508s) We don't want to use rules for Do we want to use rules for now? What >> you mean? Do you want to use >> do you want to inject them from any test right now? >> Not really. >> No, >> can do it later. >> Yeah. >> We say rules [\[25:46\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1546s) That make sense? >> Makes sense. >> Okay, that was a big refactoring. I'm not happy that I did such a big refactoring >> and neither is the computer index was outside the bounds of the array. Let's see. I guess we should have taken the refactoring in smaller steps, but I think I went a bit too fast at that. I think it's probably something simple. Let's see. [\[26:18\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1578s) Let's see. This is where did we end up? Output Where is the add stone? Here. Here. Check stones positions and remove if needed. X and Y. And we want to go to rules. Move surrounded stone. [\[26:50\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1610s) It's a dead stone color. >> Mhm. Turn matrix XUS one. Interesting. >> >> what >> it should be for Oh, what happened to my screen? Interesting. [\[27:22\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1642s) There you go. Run. Run all the tests. All right. Less failures >> this time. >> Different thing, huh? >> Mhm. >> Okay. Go game. It's expected empty. Was this interesting? Did we missed? So, what did we miss? I think now we're looking at the wrong at the wrong stone every time, [\[27:56\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1676s) Right? >> okay. So, here's what I'm going to do. >> Hold on. >> Okay, we're back. You know what I think I'm going to do? I'm going to backtrack the whole thing. >> I'm going to try to do it in smaller steps. What do you think? >> I think so, too. I think I agree. See what we did. >> What the hell happened? [\[28:41\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1721s) Okay. >> Is it to the top? Yeah. >> Yeah. >> Okay. R. >> All right. >> Okay. That was quick. You know what? But you want to try to do do a git commit for now >> and say we just have the add stone left and surround opposite color. No, which one did we just make pass? >> we made [\[29:12\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1752s) Oops. Everything just died. Show hold desktop. Okay. All good. >> yeah. Well, let me commit first still. >> Can you put that also on top of Visual Studio >> so people can see how you commit and stuff? [\[29:43\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1783s) >> I'm not very good at git. Still do punk git. What should I say? Default winner default for returning default winner. Okay. And komi. [\[30:13\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1813s) Okay. Awesome. So now we can try and do do the refactoring in a smaller way. So one way to do it is to we have a class rules, right? >> Mhm. >> And what we can do is to say yeah prop [\[30:43\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1843s) Board port and we can have a constructor here. Can you push press alt insert? Okay. And then we'll say that rules equals new rules. [\[31:34\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1894s) Just create the field rules. I did create so low down there. Okay. Next thing is we want to just move the whole thing to somewhere, right? And just say >> so we want to move is fully surrounded by. So we need to make a method for stone color matrix >> extract method right [\[32:06\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1926s) Well there's there's several ways we can do it I think one way would be to just make it static and just pass it the stone color matrix. Another way would be to actually first of all refactor all these things. Yeah. Extract a method just like you said. So that all these things are 12 m [\[32:37\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1957s) Get stone color. Let's make sure that we didn't break anything so far and just go one by one. >> Right. But >> yeah, >> I can tell already that [\[33:08\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=1988s) I mean because it's doing xus one right here. Oops. And then you also need to do parenthesis up there. >> Yep. Go ahead and fix it. All right. And it's supposed to be x - one still. >> Did was it not xus one? >> It won't x - one. But when you did the extract method, >> it just made it x. >> Then how come the test continued to pass? >> Because maybe the maybe that it was not looking maybe the surround left part did not determine it. [\[33:45\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2025s) So, you think we should have like went back and find a test, write a test to make it fail? >> Well, hopefully. >> Yeah, cuz otherwise, what was the point? I mean, it used to be like that. I'm trying to understand. >> No, it was not like that before. So, if we control Z back, how come my controls not working anymore? This is weird. [\[34:18\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2058s) So see that's that's what originally was X we had X minus one. >> Uhhuh. And it and it changed it into X. >> Interesting. >> Aha. So that might have been what broke us, right? >> Mhm. Yep. >> Interesting. >> But we still want to refactor. So can you go ahead? It will be faster if you do it on your end. The whole refactoring thing, but keep it with a minus one. All right. >> even though it >> I I don't want to change functionality. [\[34:50\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2090s) >> Alt Mr. Alt Mr. Alt is all the refactoring stuff. >> Okay. >> yeah. Okay. X - one. Yeah. Yeah. Well, actually, no. It what's interesting is that it sends X and here you have an X minus one. >> So actually it's pretty good. It was okay. [\[35:21\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2121s) >> No. >> Well, the problem would be for the other the other stone matrix because it'll be X and XUS one. >> Yeah, but we'll just have Oh, because Okay, I understand. But wouldn't it be I mean the minus one is like an implementation detail. It's part of the the way the matrix works, right? No. >> No. It's because we're we're trying to get surrounded on the left. That's why we had the XY. >> Okay. >> Right. [\[36:17\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2177s) Alt R that sucker, right? >> Okay, we didn't break anything yet. It's a good start. Now we can make it public yeah just move the whole thing up to board here [\[36:52\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2212s) And here everything just becomes board. >> Mhm. Man, just make public. Let's see. >> Okay. Doesn't compile. We have to fix this. >> Yeah. [\[37:33\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2253s) >> Okay, now we're good. 11 passed. >> Mhm. >> what else? >> We also want to do check stones around position and remove if needed. >> Okay, you want to try that? >> Right. So you just >> so >> you make the remove surround zone public so that you can call it from the outside >> and basically just move the method. Yeah. [\[38:29\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2309s) Okay. >> anything else? >> Do we want to move surrounded stone part of it? What >> do we want to move add this to the rules or >> I'm not sure if we want to add this to the rules or not. >> Well, this changes the state of the board. So, we're just telling the board to remove something or add something. >> So, it's not a rule. It's just we're just telling it to remove. Right. >> Right. >> Okay. >> Actually, it does remove only if it's full fully surrounded. [\[39:00\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2340s) >> Oh, but it's checking for the rules. Okay. Remove surrounded stone and it's calling is fully surrounded by. So maybe we should rename it to remove surrounded stone if surrounded. Oh no, actually remove surrounded. Never mind. >> Remove if surrounded stone. How's that? >> Remove if surrounded. Remove stone if surrounded. >> Okay. [\[39:38\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2378s) Okay. Are you happy with that so far? Do you want anything else? >> So, >> what about get winner? I guess that's supposed to be in the rules, right? >> Yeah. Either in the rules or something that determines winners, but yeah. Yeah, maybe it should be in the rules. >> I agree. It should be in the rules. >> Okay. So, let's see if there's anything. Should I just move move it first and then fix whatever problems there are? >> Actually, if you remove it right now, it will have the tests won't compile and I would rather that we can get the winner from the board and it will just use the rules underneath. [\[40:15\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2415s) >> Oh, >> just a forward mechanism. >> Okay. So >> so the way you did you just copy the whole method to the board and then you make a forward call it >> right. So oh then you have a board in komi mode and you have and then you have a current winner thing. >> Sure. Do we still >> So we would have to make a property for the board. [\[40:47\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2447s) Well, first of all, well, first of all, let's do the Yeah, we still need the in komi mode, right? >> So, but you can go ahead and create it. >> All right, first let me >> get color. Get stone color. [\[41:22\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2482s) No, no, no, no. In komi mode is a is a is a logical thing, right? We have that's part of the rules. Komi is a rule, right? >> I see. >> So, it's just an internal flag. Okay. >> The board doesn't care if it's in komi mode or not. It's just a state. >> I see. >> Well, at least that's the way I think about it, >> right? But the board would be setting the komi mode. >> I don't think so. I think the board would just tell the the the rules that a move was made and then it it would just either set it or not set it. [\[41:56\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2516s) But >> Okay. Oh, what's the easy way to make it into a public property from here? >> Oh, I guess >> No, you just go to the red stuff and press alt enter. >> Make local make property. >> Not why not a field >> is a field. >> Yeah, field is always better than a property >> unless you're using it public use for some reason. Okay. In komi mode [\[42:27\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2547s) And the default is true. Right. >> Right. >> That's also a field, right? >> Are you lost? >> No, I'm not lost. >> The default is white. >> Right. >> Cool. Now we can see the rules. Now we just have to forward [\[43:17\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2597s) Okay. And also now we can get rid of in komi mode. >> now we just have to let the rules notify the rules that a stone was added in which color. That's it. Right. >> Okay. >> Then it will just set it. >> Okay. So we need to make a another method for it then. >> Yeah. What I'm saying is that komi mode is nobody cares about. It's an internal state. >> Okay. So rules >> say like notify stone added or something like that. [\[43:52\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2632s) >> Okay. >> And just give it the stone color and XY just so the rules can do whatever they want with it. Right. >> Okay. >> Mhm. Okay. And this one will just be >> And we also need to to determine the current winner. Right. [\[44:23\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2663s) >> Right. >> Exactly. And we have to remove the current winner from the the board just here. >> Okay. And so then we can remove that. Awesome. Cool. >> Okay, let's try that. >> Of course. Yeah. Let's see what happens. >> Yes. Cool. >> Very cool. I like it. I like it more and more. [\[44:54\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2694s) >> Okay. >> so do we want to Okay. So now, now this also about the get winner thing. Now that we have it passing, do we want to remove get winner from the board? I kind of like it that the board is my my my main agent engine API. >> I kind of like it. It's simple. Do you do you not like it? Do you have Do you have a different API in mind? Do you always want to get Bot rules? I mean, feels like a breaking the law of Demeter here. [\[45:27\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2727s) >> Law Sean was law of Demeter. De diameter. I'm not sure how to pronounce it. The idea that you always get something dot something means you should just have the something dot something in hand. If you always say board rules, just use rules instead. Just move rules ahead. See what I'm saying? >> I I think so. >> If in my test I keep saying board. >> Mhm. >> Then something in my design is really telling me that I should do that rule should be one level earlier. [\[46:02\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2762s) And so that whatever API I'm trying to use, get winner should be on the thing I'm trying to use. So if if if I were to get rid of get winner here >> then in my tests, right, what would happen? Look at that. >> It would either be board rules.getwinner or I need an instance of the rules that I would pass to board and then I would >> and then the API kind of sucks if I need two instances to determine something. >> Right. Right? Now I need to do like rules.get winner, >> but I need to do it every time to do something. [\[46:38\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2798s) >> That law of Demeter means that I'm trying I'm trying to get the same thing every time in multiple in and it's in down a chain of responsibility somewhere. >> So if I keep getting it every time, I'll just promote it to be a first first level API >> just to keep things simple. So I kind of like that it's simpler that this way. And but you know some people may not agree that's okay. [\[47:10\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2830s) >> Okay. Where are we in terms of the Excel file? >> So let's take a look. >> In terms of Excel file, >> is there anything we can make green? >> I think the komi is green now. >> So we can mark this green. Yeah. And where is the determining the winner? >> Right there. >> Does that make sense so far? >> Yeah. [\[47:40\]](https://www.youtube.com/watch?v=cIi9iyJXyrg&t=2860s) No. >> Well, we haven't counted territories yet. We're still working on that. >> Yeah, we're still working on it. >> Hold on. Be right back. >> Okay. Cuz it's >> Let's finish things for today. Raymond, I guess we'll have to have another session. >> All right. >> Okay. Awesome. See you maybe tomorrow or or later this week. >> Yeah, >> thanks everyone for watching as well. >> Raymond, say bye. >> Bye. ## Related - [Unit Testing Denial Pattern #1: Pretending the test is no longer valid](https://osherove.com/blog/2008/4/30/unit-testing-denial-pattern-1-pretending-the-test-is-no-long.html) · osherove.com Roy getting a suite passing again after a refactoring got out of hand, like the broken large refactor here. - [Test Driven Source Control–Safe Points](https://osherove.com/blog/2011/2/2/test-driven-source-controlndashsafe-points.html) · osherove.com Proposes source control safe points tied to test runs, which helps undoing a broken refactor and redoing it in smaller steps. - [Refactoring the production code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2) · The Art of Unit Testing, 3rd ed., ch. 2 Book section on refactoring the production code under passing tests, as logic moves from the board into a rules class. ### Also linked in this lesson #### osherove.com - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) - [Refactoring String Calculator with SOLID Principles in Mind - Examples Needed](https://osherove.com/blog/2013/3/6/refactoring-string-calculator-with-solid-principles-in-mind.html) [Previous lesson Stoned and Board](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/stoned-and-board/) [Next lesson Finding a Winner](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/finding-a-winner/) --- title: "Finding a Winner" url: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/finding-a-winner.md" canonical: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/finding-a-winner/" tags: [] author: "Roy Osherove" description: "Lesson 5 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 1:01:59. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Finding a Winner 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD Pairing Sessions - Building a Go Game](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/) 3. The Sessions Lesson 5 of 11 Duration: 1:01:59 [Watch on YouTube](https://www.youtube.com/watch?v=05IPTAYRrTQ) ## In this lesson In session three the pair remove the hard-coded corner cell from the winner check, duplicating passing tests instead of changing them and changing one assumption per test. Debugging shows the board starts all black, so they first write a failing test where white should win by komi, then fix the enum and an off-by-one edge check. They loop over the board to find surrounded cells, add an edge constant and remove the assumption that black always wins. ## Transcript 7,316 words [\[00:05\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=5s) Welcome back to session three. Raymond, how are you doing? >> I'm doing great. >> So last in the last session, we finished it up with a refactoring and that we we kind of liked but then we had to finish. So my question to you is, do you want to continue to do some more refactoring because I also got some comments that the code is still not readable enough? Or do you want to continue and do some more some more? [\[00:37\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=37s) >> what did they what did they say was not readable enough? >> specifically, I think someone mentioned this flag right here. Uhhuh. >> What do you think? >> I think it's fine for now. >> Okay. >> I think we should continue. >> okay. And let's get rid of this toolbar right here again. [\[01:09\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=69s) Is it the text editor? Yeah. >> Yes. >> I didn't know that [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)") had a toolbar. No, I I made it myself. >> Oh, what happens when I click it? I just clicked. It >> launches this this one cuz I wasn't using Testr runner. >> Oh, how hacky of you. That's pretty cool. Let's see what happens. Nice. I like the green feeling there. >> Yeah. >> Okay. Okay. So, let's open up the Excel file and see where we're at and where we're trying to to go. [\[01:43\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=103s) >> Okay. So, Oh, I did not open it. So, we were trying to we have not we were working on the territories and then we decided to do a refactoring and and I got a comment about the territories that it's actually called chains. >> No, they're actually talking about what I called groups. So, when I said surround group, >> yeah, >> they're actually talking about surround chain. >> Mhm. Okay. So, >> so [\[02:13\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=133s) >> we were in the middle of something or were we just finishing? I think we're just finishing the winner or we just beginning the terminal winner with some features. >> So, we we were still determining winner. We were trying to get the black as a winner. So, the last test we had was this one. Determine winner for black while plays last. Yeah, determine the winner. At least one cell one for black and white plays last and black wins. [\[02:44\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=164s) We made it pass because So, let's just make sure we we we said board make board and we added a stone right to to the right of the black territory and another one just below >> and then the white plays a stone that has nothing to do with that. >> Right. And the way we made it pass was we just checked that this position here was surrounded by black. So as you can tell from right here >> Yeah. is fully surrounded by. [\[03:16\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=196s) >> Okay. So obviously this is only partially working, right? >> Yeah. >> Okay. So what scenario do we want to cover to make sure it's working better? >> how about surround a different territory? That way it's not only one one like maybe another corner. >> Okay. >> Or either that or we could make it something more in the middle not on a corner on the edge. [\[03:48\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=228s) >> Sure. Okay. Why did you write that test? So I can I can exactly understand what you mean. >> Okay. Okay. So maybe we'll just I mean this would basically force us to >> remember you have the test >> so this would just force us to change our code to be more general. Right. >> So what assumption are we making right now that you're you're trying to remove >> this right here? [\[04:18\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=258s) The winner is the one that surrounds one one right. So we just >> Oh yeah, the 11 one is hardcoded. Sure. >> Okay, look. >> So now just use tab. >> Oh, yeah. I'm not sure how to share. >> Well, we can say that it's a different it's it's basically the same one as before. [\[04:50\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=290s) >> Yeah. >> But it's a different cell. Right. >> Right. All right. >> So we can say a cell not corner cell. >> Okay. >> Is one not corner cell one for black or you know what? One for white. Now let's see that the white can win. >> Okay. >> and same behavior just tab to white wins. [\[05:26\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=326s) Okay, good. So, so we can either just copy the this part and make a territory for white somewhere else or [\[06:01\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=361s) We just basically just have white by itself so that it won't it won't win by komi. >> whatever you whatever is the simplest and most [readable test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)"). I'm not sure if that's the simplest. >> It's the [simplest way](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") to prove our point. That's that's what I'm trying to say. Okay. >> Sure. [\[06:50\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=410s) >> So why do you want a black territory at all? >> So that we can force because if there's no black territories then it basically win. Well, actually, no, you're right because the komi is only if there is if it's played, right? By the way, a way to delete the whole line is control shift L for line control. >> Yeah. >> Okay, that's cool. [\[07:21\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=441s) >> so why don't you Yeah, let's see. Where are you getting the result from? You started from the assert and then you started again from the beginning of the test. I'm wondering why >> because every time we type board before it would always just give me the board object when I didn't define the board. >> Sure. >> But you're right. I should probably [\[07:53\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=473s) And then I can define the winner. >> Okay. So, white territory this time should be surrounded in all parts, right? >> Right. Or at the edge. >> Well, let's do something a bit different. We don't want this. The test specifically says not corner cell. >> Okay. All right. [\[08:40\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=520s) So line three, line four. We also need line four. Yeah, exactly. Two white. The white territory is in three. And then we need a four and four. All right. >> Oh, >> I think we we the way we wrote this is a little bit different from the way we were wrote in the other tests [\[09:15\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=555s) Because this this was X. So we had X going this way and this was Y. Y was going this way. >> When you're saying this way, I can't see anything being selected. So I don't know what you mean this way. What does this >> So >> can you make a selection so I can see? >> When we did right here. >> Yeah. >> For X, we were going left to right. >> Sure. >> Was increasing left to right. And for Y, we were increasing top to bottom, [\[09:46\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=586s) Which is different from the way we've been we wrote it yesterday. So why why why are you writing it differently? >> well I think yesterday you started it that way but I didn't correct you. So you started writing it 2 one and then one two. So it should have been one. >> Yeah because X and Y are the opposites. Yeah. >> Wait, but hold on. Are you are you changing an existing passing test right now? [\[10:19\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=619s) >> Yeah. So, I should probably not do that, right? >> Well, yeah. If you think that this is this test is wrong, >> we should comment this one out first. >> Sure. >> It's an easy way to comment >> just control slash >> control which slash >> right slash forward slash. Yeah. >> All right. [\[10:49\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=649s) >> so you think that test is wrong. So create the the the good version of it. >> Oh, first I need to make it run. How come I'm getting >> alt R? I'm pressing alt R. >> interesting. >> Okay, so let's make a good >> I think because there was nothing to repeat. So now if you press alt R there is will be a repetition. Alt R repeats a did you did you duplicate the test now? [\[11:22\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=682s) >> No I did not. I just fixed it. >> You fixed it back to the way it was. Okay. >> but make sure that you run all the tests not just one. You I think you just clicked on a single test to run. >> No it ran 11. >> Oh okay. >> okay. So duplicate the test. Write it the way you think it should should be written. Hold on. Are you fixing the second test now? >> No, these are two different tests. [\[11:53\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=713s) This one and this one. We copied it over here. >> Did you copy them? I didn't see that you were copying them. That's what >> Oh, I was not copying it. I was just switching the X and the Y. >> But they're passing to me. That feels wrong. >> Well, I just make it so it's more consistent with the other tests. or or we can just we can fix it. Such as that it makes sense. >> I'm trying to understand why it feels wrong to me that you're you're changing an existing test. [\[12:25\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=745s) First of all, >> because well, I'll tell you what my guiding principle is. If something is passing, we want it we want to know it continues to pass later. So if you're changing it, you're basically removing your tracks. That's why I like to duplicate. The reason why I was saying is inconsistent is if you look at these above tests, this is X. The one is X, the three is Y. >> Mhm. >> And then the the X when we put it right next to it, the X increases, [\[12:56\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=776s) Right? So originally originally it was 21. So basically, if we want to keep it the same as the previous test, the x on this side should be less than the x on this side. >> Sure. >> So I'm just worried that the person who picks up this test afterwards will be a little bit confused like why why is it different? Why is it position different? [\[13:29\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=809s) >> Okay, I understand that. Run all the test. Let's see what happens after you fixed it. Okay. So, it's basic. It's the same as I guess I I could to I could have copied and paste it here and copy this one and paste it up there. >> Sure. >> I could have done that. But, I think it said it all passed. [\[14:01\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=841s) Yeah. So, 11 passed. It's your fa. We're good to go. >> Okay. >> How do I Is it slash >> again? Just the same the way you commented it. Control forward slash. >> Okay. >> Okay. So now that we have it consistent, we can >> So we have yeah x and y [\[14:31\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=871s) >> two and this one would be 3 1. This one would be 32. This one would be 3 three and this one would be 42. Right? >> I think it really helps now that it's it's visually arranged that way. Right. >> Okay. >> Okay. So, we can run this. It's failed. >> Okay. [\[15:01\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=901s) So, how do we want to change update this? >> So, the our current problem is that we have a hardcoded one and one, right? We're always looking for the >> for the let's see where we Oh, yeah. We extracted it to to the rules, right? >> Rules, right? >> Okay. So, one in one is no longer okay. >> So, what's the simplest thing we can do to make everything pass? [\[15:34\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=934s) So, you remember yesterday I told you imagine you're the laziest developer in the world. You have to go in 5 minutes. >> Yeah. >> so, here's another way to think about it. Imagine you're you're like your 13-year-old cousin who just started programming in C. How would he solve it? Right? Cuz he also wants to go but he doesn't have the knowledge of making something complicated. [\[16:06\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=966s) >> Okay. >> So just a way to think about these things. So where are we getting the one load right now? We have no idea where to look for, right? >> I mean, we know that we can look at 32. Basically, do the same thing we did with the one one, but I'm not sure if you want to do that. That would be the simplest way right now to the quickest way to see to look at 32. >> Yeah. >> As well. >> Mhm. Actually, you know what I'm thinking? [\[16:38\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=998s) I'm looking at this code right now is that we're always checking for black. We could have done the same exact test from before and removed the assumption about the color. >> Yep, we could we could have done that too. >> Do we want to go back? >> Because right now, here's what I think. In this current test, we changed two assumptions, both the color and the position. >> So, let's keep one of them. >> Do we want to keep the color or do we want to keep the position? >> So, let's comment this one out first. >> I I don't think we need to comment it. [\[17:08\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1028s) I think we got the test wrong. I think we we need to to to either reverse it so that black is still supposed to win but in a different position >> or that white wins in the original position. >> Okay. All right. So, let's just make it make it black then. >> Yeah, I think that would be easiest. So, I mean first of all change the name of the test. >> nonor cell one for black. Yeah. >> And black wins. >> Yeah. >> Okay. [\[17:49\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1069s) Will that test fail actually? >> Yeah. Yeah, it will fail >> cuz it's not at the corner. >> Yeah, but it it's the la the last player is white. Well, we have to make the last player white. >> You're right. >> Right. Same reason why the other test passed. >> Okay. >> Which this actually cannot be the same. It's called four. [\[18:20\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1100s) >> Yep. >> What happens now? >> Well, why is it fast? >> Interesting. So, we got the test wrong. Interesting. We're expecting black and we actually get black >> cuz current winner is last note added surrounding return color. [\[18:51\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1131s) >> Ah, so this is interesting. So we're not sure how to get it to fail. >> Oh, okay. I think we should I think the easiest would be >> actually, you know what? Here's why it's working. Because we we that that location is actually surrounded by black, >> isn't it? >> One and one. Isn't it surrounded now? >> One one would be like right here, [\[19:22\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1162s) Right? >> Uhhuh. >> And then one, two, and then two, one. >> Yeah. But when we check is fully surrounded by I think we're also checking the the ones right next to it as well. Is that possible? >> No, >> you're right. Maybe. Actually, I don't think so. This >> you can So here's a here's a trick by the way if you want to go back. [\[19:59\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1199s) All right. this. How do you go back? >> Control minus. >> Okay, that's what I did, but it didn't go back for me. >> interesting. Another way is to control Alt F7. >> Never mind. I lied. It went back for me. >> Bastard. >> All right. >> control turns it into a link and then you can click it. Oh, control. >> Yeah, control. And then you just hover the mouse over anything, it becomes a link. [\[20:31\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1231s) >> Oh, wow. Okay. >> Yeah. >> Interesting. >> Yeah. I'm used to pressing F12, but >> F12 or controlB will work as well. >> Control V and ReSharper. Okay. So, we're getting something wrong here, right? We cannot this test is wrong in in one way or the test is right and our code is doing too much. I'm not sure. >> I think the test I think the test is right and there's something wrong with our code. [\[21:04\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1264s) >> So we have to write a test that fails. It proves that there's a bug. >> Okay. >> You agree? I mean, I was thinking it might be easier to just walk through the code and find >> Yeah, I I I definitely think we can we can debug the code. What I'm saying is that we cannot change it because there's if you think it's obvious that there is a bug in the production code, we need to be able to later reproduce it with a test before we fix it. >> Okay, >> agreed. [\[21:34\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1294s) >> All right, I agree. But I'm not sure how >> well first of all we have to to realize what the problem is >> right. >> Okay. So what we can do is we can basically a break point here. >> Oh I see. So we we do break into it find out the problem and then >> then write a test that recreates a problem. >> I see. Okay. >> Basic forensics. >> All right. So you go all the way up here. [\[22:06\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1326s) I can't see it. You say test with debugger. >> Okay. Okay. So, let's step into it. Let's see what happens should be false, right? >> Sure. surrounded >> and is it just let's see what it returns. [\[22:36\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1356s) >> Oh, I forgot was the command to skip back up this one. >> Never mind. >> All right, >> just F10. Yeah. >> So, it says surrounded is true. So, you are right. >> Okay. So, but we can't just create a test that proves that is surrounded by returns true or false because that doesn't is not a [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)"). It's a it's an internal thing. So the only thing we need to say is that something else doesn't work because of that. [\[23:07\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1387s) Something that should have we should have gotten a different result when we're getting a a real one. So is fully surrounded by returns true. Let's see why it checks it returns true. Now we can actually jump into it with F11. >> Okay. >> Okay. Let's just see which one returns true at some point. >> Surround on left equals true. >> Yeah. Well, that's okay. [\[23:38\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1418s) >> Well, it's one it's one one. Oh, yeah. Zero 01, right? So, that's okay. >> Okay. Surround on right should be false. Let's see what happens. I can't see it. Surrounded on right is true. >> Interesting. X + one is so this is two two one I'm interested what the board is. So this is looking at the surrounded [\[24:11\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1451s) Get stone color. So it should be so everything is black. It says I thought we made it so everything is empty at the beginning. >> Everything was supposed to be empty, >> right? >> But we Yeah. >> So I guess our our test could be we we initialize the board and we verify that it's empty. >> that would be that that would be one way, but I would rather verify that there is a bug where for example we have something that's not surrounded [\[24:47\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1487s) And so the winner will should be the other color and we get the the the the one that's wrong. >> Okay. >> For example, we can create a test almost like we have right now. >> Mhm. >> but we have a stone that's not to the right. So there is no winner. So, we should be getting a white by komi, right? >> I see. I see. >> But because it thinks it's surrounded, it's going to be false. [\[25:18\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1518s) >> I see. >> Does it make sense? >> Okay. Yeah, that makes sense. >> And just to make sure, let's see what surround on bottom and top says. Okay. >> It's F10 and F10. >> True. Sorry. >> It's going to say true because >> Yeah, because everything is black, >> right? [\[25:55\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1555s) You want to write this test? >> Okay. Let's see. So what's what's going to happen is we're going to write a failing test. When we make that test pass, this test should start failing. >> And then we can fix it. >> Okay. >> So, you're going to just you're going to just add the test. You're not going to comment this out. >> No, this test passes. We're going to use it later when it stops passing. [\[26:25\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1585s) Determine winner. Own any cell. White should win. But wait, >> actually, I realized this one. Oh, okay. Oh, I see. I see what you mean. >> Okay. [\[26:57\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1617s) Okay. >> It's different from a test we already have because the black has already played, >> right? Black played but doesn't own any territories, right? Okay. >> and in that case, we can say make board add stone black at 3.1 and that's it. Right? >> I'm going to leave these lines. I should know that. But [\[27:29\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1649s) >> what? Oh, you we missed you think that the white should have played already, right? >> Right. But then I think you're going to get white because the current winner. >> Yeah, I we're supposed to get white, but but I think we're going to get black. That's my point. >> Okay. >> You because everything by default is black. >> I see. You're right. You're right. I agree. I agree. >> so we're supposed to be getting white here because by komi we should be getting white. [\[28:02\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1682s) So red once white should win by komi, right? Make sense. Or does komi not play into anything? >> No, it it should be owned by komi because neither of them own any territories now. >> Okay. So, komi only stops applying when someone owns a territory. >> Yeah, none of them own territories. So, white should [\[28:40\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1720s) Ah, yeah, it's debugging because that what we did before. That's the last thing we did. So, just right click here, run tests. Cool. >> White, but was black. That recreates our problem. >> So now we can go ahead and say, "Oh, there is an initial board that's supposed to be everything's supposed to be empty because our enum here. >> Let's move our enum here for a second. >> Good job. >> Sorry. >> You need to make it int. [\[29:11\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1751s) Declare intum." I forgot how you do that. >> And in enum is int by default if I remember correctly. So why is it not setting it as zero? >> Because we have to set the other ones. >> The solution would be just to move empty on the top. That will >> Sorry. >> Or do that. >> Let's see what happens. >> I was going to put empty on the top. >> Oh, two fail now. >> black wins. Black wins. [\[29:41\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1781s) But you notice that our test currently passes. The new one. >> yeah, the new one passes. Okay. Right. Cuz in our test, white should have won. >> Right. Right. Okay. >> Okay. So, we have one test we expected to fail, which is a not corner cell. Right. >> Right. That one we expect to fail. The first one though we expect to pass. >> At least one cell one for black and white. [\[30:11\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1811s) Well, at least one cell one for black and white plays last. Black wins. okay. So I would suggest let's fix the let's comment out the test we have that we that we expected to fail so we can focus on the one we don't we didn't expect to fail >> which is this is the one we expected to fail. Right. >> Right. [\[30:48\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1848s) Oops. That's not what I meant. Control Z. Control slash. >> you do it. Control forward slash. I think our keyboards are just different. >> Okay. >> Maybe. >> Alt R. Okay. Now, let's see what the hell happened here. Double click here. And where are we? [\[31:19\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1879s) >> We're at the top. That was pretty cool. >> Oh, yeah. Okay. So, now we can actually debug that and see what happens. Okay. Oops. >> So, you press F11. For me, it doesn't work. >> Oh, really? [\[31:49\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1909s) Okay. >> All right. So, >> okay. F10. Let's see. Is fully surrounded by what does it say? False. That's okay. That's good for us, right? >> No, it's supposed to be true. >> But it's not. It's How is it supposed to be true? Oh, at least one cell, one for black. That's true. So we have >> So are did we get the test wrong? [\[32:19\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1939s) >> The thing just is not surrounded. >> I remember remember we were talking about how we do not I I was talking about how we did not have test verifying that surrounded on the corner or on the edge. And then he you thought maybe it might it might it might pass or our implementation or took care of it. So we decided to go >> other stuff first. >> Okay. >> So I think this might be relating to that where we did not have tests originally to verify that checking in the corner that it's surrounded actually passes. [\[32:59\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=1979s) >> Okay. So why don't we step into is fully surrounded by and see exactly what the problem is. F11 that sucker. Okay, >> so start on left is going to be false. Oh, what just happened? What did I just do? Why? Why you look funny? Oh, get out. F10 sur is false. So I think the issue is that we're treating the boundary as zero here. [\[33:36\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2016s) >> Yeah. >> Where >> it should have been. >> Well, where we wanted it to be one through 19 instead of zero through 18. Like we didn't want the for the term. >> We should just say x is bigger than one. No, x is smaller than two maybe >> or x. Yeah, >> because x is one right now. >> Right. So if x is smaller than two then yeah we're surrounded on the left or actually just if x is equals one. No. [\[34:08\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2048s) >> Yeah. Yeah. >> So it's a wrong zero. Yeah. So x equals 1 would be the change here. >> Okay. >> And for surrounded on top it's y equals one. But let's see what happens. Let's just fix this one and see what happens. >> Okay. So should we keep on stepping through or just run through the rest? Whatever you think. >> Turn on to the rest since we already know what we want. Okay. So, we don't want to fix this equals one. [\[34:40\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2080s) >> Mhm. Let's see. Yeah. Now, don't repeat. Just run all the tests with a menu for now >> because it will repeat the debug action. >> Yeah. >> Wow. Awesome. What the hell? I think maybe a lot of our tests we we treat X as Y. Maybe that's the problem. No, I don't think that's it. I think Oh, so what's that filling acid above and surround color index out of range? [\[35:17\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2117s) Next one's out of range. because well, how about x is smaller than two. I'm not even going to try to fix everything. I'm just going to say if x is smaller than two, maybe that's a simpler fix Okay. All right. So, at least one cell one for black and white plays last. Black wins. So, I think we should also fix the Y for smaller than two. [\[35:59\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2159s) >> Good pass. >> Wow. >> All right. >> Okay. Okay. So, let's let's uncomment the the other test and that should fail. Let's see. Right. >> Okay. So, determine winner. Not corner cell one for black. Black wins. But it was white, [\[36:35\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2195s) >> right? Because we're we're just >> because now that now we're back to fixing the one and one, >> right? To fixing that hard-coded X and Y for always at the corner. So, now we can actually go and fix that. Right. >> yeah. >> Now that's the actual thing we wanted to try. We were yak shaving up until now. So So that's our problem is surrounded by we have a black that's surrounded but it's not one and one. Okay. So [\[37:06\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2226s) What's the easiest way to find black is the winner? Remember we assume that black is the winner. So we just need to find that black has surrounded one. >> Well, the first easiest one would be just check this territory. But would we want to do that? Is that what you mean by simplest way? >> Well, simple does not necessarily mean well remember simple is first of all as close to the top of the message as possible and less indented. [\[37:41\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2261s) If we just check two places, it just leads us down a rabbit hole of continuing to check two places, three or four places. So, assuming that it will be actually easier to and simpler to just write a loop that goes through everything maybe. >> Yeah, that's what I was think that was I think was the next simplest solution. So, >> actually, here's something simpler. What if we didn't use a loop? What if every time we added a stone, we would check if it's fully surrounded by? [\[38:14\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2294s) >> Every time we added a stone, >> we would check for if for around it if something is fully surrounded. >> Right. We already have a remove stone is surrounded. Right. >> Right. Right. So that means every time we add a stone for each of its neighbors, we check if it's surrounded. >> Yeah. We already have the infrastructure in place. We just in the place where we would have removed the stone, we would also just declare the winner as well for now. >> Okay. [\[38:44\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2324s) >> what do you think? >> I want I I want to see you do it. I'm not sure if I fully understand. >> Okay. So remove stone is surrounded. Already knows if something is surrounded, right? >> Yes. So if it's fully surrounded right now, we always assume that black is the winner. Right. >> Right. >> So we just say >> right now we doing it's fully surrounded by white only in that code. >> Sorry. >> Right now we're only doing fully surrounded by white. [\[39:19\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2359s) >> Ah interesting. So that's another thing to take care of. But let's see it's always surround. So that's something we will need to take care of as well. So I would say also so that we won't forget to do it later. We would say to-do remove assumption [\[39:50\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2390s) That checks that removes move stones only if they are surrounded in white cuz that's a bug. Right. >> Right. So one way to fix this is to actually to take that as a parameter and then >> right >> move surrounded if [\[40:23\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2423s) Cuz I'm pretty sure we have two ways to go about this at least. We can either do this and then when we know that it's black then just declare the winner or does if someone has something fully surrounded just declare that as the winner in the rules. >> Okay. >> I mean rules is fully surrounded by is already sending stone color white. Agreed. >> Mhm. >> Actually yeah we don't have to go far. We go to rules is fully surrounded by [\[40:55\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2455s) And we'll say here if fully surrounded and last what was it? Current winner equals surrounding. [\[41:33\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2493s) >> Interesting. All right. Now the get winner won't have to check if something is fully surrounded. current winner, >> right? So we would want to do if fully surrounded by in the ad stone, [\[42:04\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2524s) >> We're we're doing that, >> right? Okay. >> Okay. So we ran the test. Two failed at least one cell one for black and white plays last. Black wings failed and not corner cell one for black. Black wins failed. So either that didn't work or I missed something. >> No, I think you're only checking if fully surrounded for that current [\[42:36\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2556s) Current stone >> whenever we gather position. >> I think you need to check for the neighbors. >> Okay, you know what? Let's do it simpler. Hold on. I'm going to undo. Okay. [\[43:06\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2586s) Just this and here simplest thing I can think of is just to do a loop over everything and just count the points. >> Yep. >> Basically, so for int i in what was it? Board dot or actually >> sorry oh yeah equals 0 to or is it one >> one? Well, we're treating one as the edge, right? [\[43:38\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2618s) >> One one is smaller than board dot. What was the name of that thing of that const size? >> Yeah, I think it's public. >> We'll make it And I think it's supposed to be while I is less than equal to. [\[44:18\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2658s) Cool. Is that supposed to be public or private? Let's see. Nope, that doesn't. So, I'm missing the name of that. Let's see. board size was without an underscore. That's it. Okay. Make it public. And now we need an inner loop, >> right? >> Yep. >> Four [\[44:49\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2689s) And J. Is it the same? Right. >> Right. So, we want to equal one also. Yeah, >> our board size right now is 20, right? So it should be >> should be 19. [\[45:21\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2721s) >> Is it 19? >> Yeah. >> 0 to 9, >> I think. So we stopped. We did we tried changing it but we backed out on it if I remember correctly. >> Right. >> We can go back there. >> The thing is we want to treat the edge as 19 the array is zero between 18. Right. >> Hold on. Yeah. >> So when it does check the edge for 19 you may get an out of index exception. [\[45:53\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2753s) We would say here basically we would we would just back out on the first surrounding. So we would say just come on if is fully surrounded by we'll just use I injure [\[46:40\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2800s) Stone color black. How's that? >> Yeah. >> And now we don't need to do anything here. >> Mhm. >> That makes sense. >> Yeah. >> Well, we still have those two failed, but it's still index. >> So, I guess we should be Yeah. >> Okay. [\[47:18\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2838s) >> Stone color. Where is that gotten from? >> It's fl Oh, it's because I I know why. >> Okay. >> It's because we did not we're not checking the edges for right here. So, right and bottom. >> Mhm. We're not taking >> should be board size minus one. >> All right. >> Small smaller than board size minus two I guess. [\[47:53\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2873s) >> Well, it's going to be greater than because we wanted to return true, right? for upward size minus one >> one. Why do we have >> Well, you still have to put it in brackets in parenthesis. >> Do we have to put it in brackets? >> I think it's more readable. Okay. [\[48:42\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2922s) Okay. >> It's bigger than board size minus one. Actually, I would say it is. It's equal to board size or it's bigger than board size minus two. I think it's the same same deal. Cuz if it's bigger than both sides minus one. Sure. Okay. You know what? Sure. >> So, let's debug this thing. >> All right. >> But we can see exactly where we got the message here. [\[49:12\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2952s) Stone color get winner. Then we don't have a line number. Yeah, we do. some color matrix here and get it from this line. >> Okay, >> let's run it on bottom just just this. You see? And there we have this one. [\[49:43\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=2983s) It's just minus two. So, this does sounds feel like we're kind of like just hacking our way through like >> Oh, yeah. Definitely. >> Together. >> Well, I It's more like a trial and error because this is I mean, it's known to be like an error and an off by one error. So instead of just thinking it through, I'm just going to let the compiler and the tests let me know when I'm done [\[50:16\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3016s) Because I know that the range is one here or one to the other way. So I'm not going to bother thinking too much about it. If I realize that that's not the real problem, then I can start delving into it. But I'd rather just focus on like really difficult stuff here. This is simple. It either works or it doesn't. And we know that this is where the line this is what we changed. So it's kind of simple. Okay, that makes sense. >> Okay. So, so now that we have everything passing, let's refactor a bit because I don't like these number twos there. [\[50:48\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3048s) >> Yeah. >> So, we can make them into const, right? >> say again. >> So, we can make them into const numbers. >> Okay. Right. >> With a good name. What would a good name be though? >> if it's smaller than >> like the edge, [\[51:21\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3081s) >> let's just call it edge. >> Yeah, >> That makes sense. >> Sure. >> Okay. So we can go ahead and say control shift R. Introduce variable or field replace for call it edge. Make it a static. It's not an edge. [\[51:51\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3111s) It's an edge. What's that? So he's fully surrounded by surrounded on the left. We don't need to do this check [\[52:24\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3144s) So, what did we just add? What feature did we just add? >> We added in the >> Oh, remove Oh, we removed the assumption of one and one. Actually, right. >> you you broke up a little bit there for me. >> We we removed the assumption of one and one. >> Right. Right. >> Hold on. Okay. So, we we removed the assumption of that black is always at the same location. So we said if we had a black that's not in the corner, it would still be found as the winner. [\[52:59\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3179s) >> So now we can remove the assumption that black is always the winner. >> Yep. Yep. We can do that. >> So we can say control Determine winner. I think it might be easier if we copy the one of the other tests. >> Oh, did I copy the wrong test? >> Yeah, the test above that one. >> Sure. [\[53:30\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3210s) >> And then replace it with colors. >> Not corner cell one for black. Black wins. >> But now we're going to remove a different assumption. Determine winner. Not not corner cell one for white. >> Mhm. and white wings. Yep. >> White. White wings. So, we're just going to switch up the colors. [\[54:00\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3240s) >> Yep. >> white. Let's do there. And actually, this means black. >> Yep. Black, white, blah blah blah. White. Okay. And the last play is by black. [\[54:34\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3274s) Sure. >> Yep. And then you assert are equal. >> Oh, that's true. Okay, determining not corner. So one for white, white wins or yeah, white wins. But it was black. So now you can just say just return [\[55:08\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3308s) Get or is it board get stone color at INJ, right? No, because it's fully surrounded by it's going to return false because it's only checking if surrounded by black, not >> inj plus one. >> Huh? >> No, I don't think it's going to even enter in here because this is going to be false because it's looking is surrounded by black instead of white. [\[55:40\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3340s) So, I think the easiest one would be if we go back. Oops. If we do this. >> Yeah. Well, that will pass. It's pretty horrible. And then we'll make it nicer. >> Yeah. >> Yeah, I agree. >> This should pass. Yep. Okay. >> Now, kind of make it pretty. >> Now, I think we just need we need the fully surrounded by not to take a color. [\[56:10\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3370s) That's basically it. and to have a version of that >> where we don't care about the color anymore, >> right? >> So imagine we did this surrounded by and then we would just say is not equal to empty, >> right? [\[56:47\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3407s) Stone color empty, etc. >> Mhm. So, we have a version of this. And now we would go back to >> would we would it be would it be okay to change the return type or like I guess like if it's fully surrounded by it returns. >> It's just a boolean, isn't it? >> Right. But I mean it might be simple. >> Yeah. But imagine that it's partly surrounded in white and then partly in black. [\[57:20\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3440s) What would you return if you return a color? >> Right. Well, I don't think that >> method right now actually solves that problem, but I think we might need to introduce a test to show that that fails. That should fix it, I think. Did I forget something? >> What did I forget? Oh, yeah. First you need to do this >> just [\[57:57\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3477s) >> have something to do with the fact right now. >> Sorry. >> Right now you're only returning stone color black. >> Oh yeah, right. Good catch. The fact that it's 3:00 a.m. here might delimit my pro abilities for a bit. Board get stone color at I and well it's surrounded by but we can't assume that we get a surrounded by but I'm going to assume it's J plus one. >> Okay. >> let's see what happens. [\[58:41\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3521s) Now I'm just toying with myself. So what do we do? >> we still need to get the other version. >> Yeah. >> What do you think? >> I was thinking that the fully surrounded by can return the color if it's surrounded. But maybe have out parameter. I think we're No, I think I think you had it right the first time we just say is surrounded by [\[59:16\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3556s) Stone color. I think that would be the most readable and simplest. I think that's just >> Yeah, >> I had I had to I had to >> Yeah. And then you had two, of course, >> right? But it's still more readable and than anything more generic than that. I think I mean I I kind of like it. >> I kind of like it. [\[59:47\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3587s) >> I mean I would have been nice to just do it in one. >> Yeah. >> But we can't assume that we know which color and from which side, >> right? >> Agreed. >> I agreed. You also might need to change back the >> just remove that. I'm going to remove the other is fully surrounded by. >> Yeah. >> Come on. There it is. [\[1:00:24\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3624s) Okay. So, but we still have an assumption here, right? The assumption is that whoever has won any kind of territory is the winner. >> Yep. >> So we need to start counting territories, right? >> Yep. So what we can do is we can have but first of all let's commit. >> Okay. [\[1:01:03\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3663s) Our shopper. >> you you'll do a git ignore for that later, right? >> I Yeah. Should I ignore those stuff? >> But not not for now because I think we're going to break for for now. It's been an hour. I'm going to go to sleep and we're going to continue at a different time. >> All right. So, what should I name this? Winner by color and position. [\[1:01:38\]](https://www.youtube.com/watch?v=05IPTAYRrTQ&t=3698s) Territory position. Yeah. Okay. But but not not with count. >> Sure. >> All right. Cool. >> Cool. Okay. Thanks Raymond. I'll see you later. >> All right. >> Bye, everyone. ## Related - [When should you remove or change a unit test?](https://osherove.com/blog/2005/4/3/when-should-you-remove-or-change-a-unit-test.html) · osherove.com Argues passing tests should not be removed or changed, the reason the pair duplicate tests rather than edit them. - [A Unit test should test only one thing](https://osherove.com/blog/2005/4/3/a-unit-test-should-test-only-one-thing.html) · osherove.com Guideline that each test checks one thing, matching changing one assumption per new test. - [TDD in .NET course - Day 2 Learnings](https://osherove.com/blog/2011/8/11/tdd-in-net-course-day-2-learnings.html) · osherove.com Notes that TDD is about removing assumptions one by one, as the pair drop the hard-coded corner and black-wins rule. - [Changes forced by failing tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_155) · The Art of Unit Testing, 3rd ed., ch. 8 Book section on changes forced by failing tests, relevant when the all-black board breaks the komi expectation. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 #### The Art of Unit Testing, 2nd ed. - [First steps with NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3), ch. 2 #### osherove.com - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) [Previous lesson Colors and Winners](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/colors-and-winners/) [Next lesson Total Noob Fail](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/total-noob-fail/) --- title: "Total Noob Fail" url: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/total-noob-fail.md" canonical: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/total-noob-fail/" tags: [] author: "Roy Osherove" description: "Lesson 6 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 1:26:57. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Total Noob Fail 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD Pairing Sessions - Building a Go Game](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/) 3. The Sessions Lesson 6 of 11 Duration: 1:26:57 [Watch on YouTube](https://www.youtube.com/watch?v=OTgudmmPuGY) ## In this lesson Session six starts with five tests failing on one machine but passing on Raymond Lim's, caused by line breaks in a string the test code splits. The first cell strategy, which really returned the last cell, becomes a strategy that counts each color's cells, and a planted bug shows the new test can fail. After removing the assumption that the surrounding color is white, work on two connected stones ends with finding X and Y swapped in the test's fill board helper. ## Transcript 8,884 words [\[00:05\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=5s) Hello everyone and welcome back to session number six. Here I am with Raymond Lim and this time we've decided to do something just a bit different. We're running our tests. We're we moved things to my machine and this time something weird is happening right now is that we have five tests failing on my machine but getting the same version the latest version of the source code on Raymond's machine seems to run all the tests and they're passing. So we've just decided to start debugging one of the tests just to figure out what's going on. [\[00:35\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=35s) We we thought maybe we should just record this and u see where this leads. So, I'm just debugging the first cell winner strategy here to see what's going on. Raymond, I'm guessing so far you have no idea as much as I am what the hell is going on, right? >> Yep. No idea. >> so we're surrounded by surrounded by And here it's just just going through and going through. [\[01:06\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=66s) So when you look at the get winner on your machine, do you see anything different from this code? >> let me take a look. >> The test as well. Maybe the test is different. Did you by any chance tab all the tests without running them? >> No, I ran them. I just ran them right now too. So, [\[01:37\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=97s) Is that trimming? And there's a trimming going on here. What the hell? Covered by night and five failing tests. Execution time per test is zero. So, it's interesting that this isn't covered by the tests. So the failing tests are they're all about determine winner and add stone to empty position position is filled. [\[02:07\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=127s) That's like the most basic thing. >> You see this right here, >> right? This one's failing. >> Yeah. Interesting. So this is the most basic thing. >> Check it out. >> With debugger [\[02:41\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=161s) Position status turn position status matrix. Yeah. What is position status matrix in this case? They're all empty. fill board. I guess fill board is the culprit here because it's not filling out things here. [\[03:30\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=210s) So, I'm not sure. Let's see. Beat that for a second. [\[04:02\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=242s) Now there are still no lines. That's the problem here is that the split on my machine. Hey, you know what's going on? I think you want to >> Did you >> did you accidentally edit it? >> Yeah, I think I'm figuring it out. So, here's a thought. You know what? I think the local on my machine is messing up with the strings and the >> slash r/n thing. >> Yeah. So, what's the local on your machine? >> I don't know. I never looked that up before. I'm guessing US American [\[04:34\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=274s) >> local. What's the local on my machine? Format is US. Location United States. Additional pretty sure there's a regional regional. You don't have any like anything special going on? >> No, I I don't have anything special. region. [\[05:05\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=305s) >> Maybe it might be the git GitHub thing pushing up, pulling down might give a No. Yeah, maybe it's probably your machine. So on my machine there are no SLRs. On your machine there are >> Yeah, >> that's interesting. That makes sense though. if there if if if our machines are the same. I mean, can you can you open your regional settings and tell me what what things look like on your end? [\[05:47\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=347s) Everything looks the same so far. Yeah. United States settings. >> language for nonuni code programs is English. >> maybe that's the difference. But what about additional settings about numbers, decimal symbols, currency, time, date. [\[06:20\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=380s) So this is the point where I would go and say C sharp string slash R not found something like that. Maybe slash are using strings custom numeric formats [\[06:55\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=415s) Slash and slash r. So we went all line breaks in a string place line breaks through the stapes string literal character classes. Yeah, there's something about the strings here that makes those things not run on my machine. So we have to get rid of it. >> Mhm. >> So I'm trying to understand what it is. Now there is a name for the strings that start with this. They're are they called literal strings? What's the name of that? [\[07:29\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=449s) >> I don't remember. >> Sharp. Line breaks. Literal strings. Not sure if that's the name. Oh, string literal. Yeah, multi-line string literal. Is there an easy way to create a multi-line string literal? Yeah, blah blah blah. Yeah, that's the we don't have to escape special characters. It's verbatim string though with the sign verb [\[08:05\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=485s) String new line slash r slashn c that's interesting. I'm I mean I'm kind of stumped here on what is to be done to solve this problem, >> right? We could go the [\[08:40\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=520s) The route where we would split two times like to check if there's a slash r or slashn because you can see there's only slashn here. Now when you debug in your part on your end do you see slash ends or slash ends and slash rs in this same line. >> Oh okay let me try that. >> This is from the same test [\[09:13\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=553s) The add stone to empty position. >> Okay. You just highlight it on the split. Mine says slash r/n >> after the after after the numbers. >> Yeah. >> Wow. >> Yeah. Mine mine says slash r slashn. >> Maybe it's a different Visual Studio version. [\[09:44\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=584s) I mean, what version of Visual Studio are you running? >> I think professional. Is it >> is it 2010? Yeah, it's 2010. >> It's probably I think mine is ultimate. So ultimate parses string better obviously. >> Not sure. I have no idea. Okay. So we can you know what? I'm just going to go to brute force now. I don't want to deal with this too much. So I'm just going to say [\[10:15\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=615s) If >> mine is ultimate also. >> H So, sometimes it is, sometimes it isn't. Is that what you mean? >> Maybe. How about you just split it first by slash r slashn and then and then split it again. Oh god, feels so dirty. [\[10:49\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=649s) This >> I wonder would that work on your machine though? I can try right now. >> You can try right now. Right. >> Yeah. Or split. I think it just takes all these literals anyway. But I think on your machine won't work because >> it still passes for me. >> Still passes. >> Yep. Yep. [\[11:19\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=679s) So, we don't need a slash R at all. >> Oh. Oh, I didn't try it without the slash R. Let me try it without the slash R. >> Yeah, still passes for me. >> Yeah, that makes sense because we trim everything anyway. More lines. So, okay. >> So, just change it slash in. >> Sorry. >> Cool. Yeah. So, I agree with you. Just change it to slash in. >> interesting. NCrunch disable and NCrunch enable. [\[11:53\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=713s) >> Oh, it's not passing for you anymore. >> It is, but it's not. It seems like it's not running. Seems like it's not running the test. >> Oh, it's probably because it doesn't considered it changed. Maybe. >> Whatever. At least we can continue now. >> Sweet. Okay, so in our last episode we created the [DSL](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6 "Building a test API for your application (The Art of Unit Testing, 2nd ed., ch. 7)") and now we have the tests on the left and the production code on the right. [\[12:26\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=746s) So what we can do is to basically I don't know just try to continue. >> Yes. >> Yes, please. Well, >> the thing is that we we're running into that test case that's passing but we're expecting to fail. the last two test case we added. >> yeah, and you said that you found out the reason why. >> Yeah. So the reason why was because we changed the behavior of the first cell strategy. [\[13:00\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=780s) So if you look at the code for that, it's actually returning the last cell found as the winner instead of first cell found as the winner. So if we go to first cell strategy we should rename it to last cell based on >> Yeah. >> this. >> Right. >> So let's rename it [\[13:31\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=811s) Last. So winner strategy. >> Okay. And to make the test fail, you can just switch the Hold on. Where's my mouse? This one with this one. I don't know if you can see my mouse. >> Mosquito. Sorry. >> You were saying >> you can switch this one with this one like the right side and the left side. >> Let's create another test that recreates that. >> Okay. [\[14:07\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=847s) And rename it determine winner. And what's the difference? How would you name it differently? >> black owns last cell found. I don't know. I don't want to kind of the thing I feel like putting that will I don't put kind of put the strategy into it, right? We don't really want to put the the the implementation details into No, but we do want to make sure that the order >> of winning doesn't matter of owning. >> Okay. Sure. [\[14:38\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=878s) >> So, it's it is about order. So, how would you rename it? >> Black owns one cell, white owns two cells, and black goes last. >> Sure. >> Yeah. And the difference is what would you change here? >> So I would change >> go ahead and change it. >> All right. [\[15:31\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=931s) All right, there we go. >> Okay. Maybe we should do it this way, actually. How do I think about it? Is there a way to move right on to the side? Never mind. Okay. Okay. So, how would you fix this? >> So, I would change the last winner strategy. [\[16:03\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=963s) >> Yeah. instead to returning the last winner, you would instead count you have a count for each stone color and then you return the one with the greater greater count. >> So we need to start counting. >> Yeah. >> Okay. So maybe. [\[16:36\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=996s) Okay. So, what's the [simplest solution](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") that can make this everything pass? Do you have anything in mind? >> so just in declare two variables like white white stones, white territories, black territories and both set them to zero. And here we just >> like increment it. [\[17:06\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1026s) Yeah. >> okay. So, white cells++ and here we would say sorry black cells plus+ and >> and then yeah so it's kind of like if they're equal to each other return empty else return the bigger one. [\[17:39\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1059s) What's the simplest that will make everything pass right now? Is there anything simpler? Like yeah, if >> white is greater than black, return white. See? Oh, that didn't work yet. [\[18:10\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1090s) Turn black. Oh yeah, that's why. Okay, still didn't make it past. >> So actually instead copy in for add another if statement if black is greater than white. And just change it. Yeah, black greater than white. And then for the last one, return stone. [\[18:48\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1128s) >> Interesting. So, what's failing right now is you can see here covered by six passing and one failing test. Black owns two cells, white owns one cell. This is the one that's failing right now. >> Okay. Could you go look at the test? I want to check if the test is correct. >> And what was the filler message? >> The what? >> What was the failure message? [\[19:19\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1159s) >> Oh, you can see it here. Expected black but was white. >> H. So, I'm thinking maybe we're not using the thing here, the strategy. So, we can say test with debugger. [\[19:50\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1190s) Step into this, go into rules, go into the result. The result here is empty. Okay, >> But black should have two, white should have one. Unless we're not counting the winners correctly. >> Oh, that's not what we meant to have. This one. [\[20:23\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1223s) Yeah, sure. And here, white cells. So we would have I'm just going to go through and say right here white cells black cells too. So we have the same number. >> Wow. >> Should we have the same number here in this test? >> No, we shouldn't. There should be only one white, two black. >> Okay. So you want you want to go back to the loop and step through it. Like check two two [\[20:57\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1257s) Actually. Just put break points inside the if >> inside the if statements. And >> sure. >> >> just going to go here and say >> well you can just move the the arrow up to the >> top right there. Yeah. >> Okay. So we have white cells here. >> that's one. >> Okay. I see why now. [\[21:28\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1288s) >> What? Because there there is there is a white cell right here. >> But in black but black should have three then I should know that this is two of them. I see. Okay. So white does have two. So there's something wrong with our test. So we just need to move everything aside by one and then that should pass. >> Awesome. >> Very cool. Found a problem with our test. >> It would have been much harder to find if this wasn't visual. >> Yeah. If if we didn't have the DSL. [\[22:00\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1320s) Yeah. >> so it's like this. >> Yeah. >> This like this. >> That should be >> just say zero at the end. >> Are we still meeting a nine though? I mean is that greater than nine? 1 2 3 4 5 6 7 8 Oh, it's it's at zero. Okay, it's fine, I guess. Yeah, >> we don't care. >> Yeah, we don't care. We don't check right now. So we can actually say [\[22:31\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1351s) That make sense. >> What did you just do? What happened? >> Remove this line. >> Oh, okay. >> Yeah. >> Okay. Seems to be passing now. So now the question is how do we trust it and see it fail when it should fail, >> right? >> See it fail. Right now we saw it fail for the wrong reason. >> Okay. >> Now we just made it pass for the right reason, but we didn't say see it fail for the right reason. [\[23:02\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1382s) So we can't [trust](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134 "How to know you trust a test (The Art of Unit Testing, 3rd ed., ch. 7)") it. Maybe it's always passing. >> So we we should revert it back to the original implementation. >> No, not the test. We should we should go to the we should find the place in production code, >> right? that we can comment out to actually create the bug that this creates that this tests for. Black owns two cells, white owns one cell, black wins. [\[23:32\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1412s) >> So, you can add I mean maybe revert our change in the prod product code back to original. I don't know. Do we have to do that? No, we have to find if we want to trust this test, we have to put a real bug that this test tests for and see it fail when it should fail, >> right? >> That was our original implementation. >> If I if put a plus here for example. [\[24:04\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1444s) >> Okay. >> Yeah. Plus. Okay. Like this. something should fail. But not this test >> because it's not testing for two too many black cells here. H it's testing for black owns two cells, white owns one cell. So if we have two many white cells maybe or yeah actually if we comment this out [\[24:37\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1477s) This test should fail just like we wanted to. Right. >> Now, that seems weird, but I just want to make sure that this test is is actually testing what it's supposed to. >> Okay. >> Go away, Dropbox. Anyway, okay. So, I I trust it a bit more now. It seems weird, but in [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") when you when you start testing with a test that fails, you're actually saying, "I'm testing the test because the test should fail in this position." Then you make the test pass without touching it because you're actually fixing production code and then you should see the test pass. [\[25:19\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1519s) >> That's basically a way of testing the test because you've seen it fail when it should and you've seen it pass when it should. >> Okay. But what happens if you realize the test was wrong the whole the whole time and now you've fixed it and it's still passing? How do you know it fails when it when it when it needs to fail? >> Okay. >> So, you need to find a way to trust it. That's what I was looking for. I think it was okay this time. >> Okay. >> Okay. So, we've just changed our strategy. So, maybe we should name our strategy to [\[25:50\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1550s) >> most cells win. >> Winner by count strategy. Okay. >> Okay. Yeah. >> Cool. >> Okay. So, now we have a winner based on actual counts. >> Mhm. >> Right. Do we want to add another feature? Do you want to add another test that proves this? >> I think the the amount of tests we have right now proves it already. [\[26:22\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1582s) >> Yeah. But what about the feature where we want to have multiple points here? That's one of the features we want to have. Right. >> Right. >> So we can create that feature now. >> Do you want to you want you want me to try and do it or do you want to try it? >> No, but the thing is that we don't have the feature to detect that area is surrounded by you know I mean we don't have that code right now. So I think we need to break it into [\[26:52\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1612s) Two two steps. one to detect that two spaces connected to each other are surrounded by a group. >> Sure. >> And then we can check that the amount of points >> it's greater. >> So is there is there a test that you can make without checking the amount of points or getting the winner >> that proves that you can detect this? What test you want? [\[27:23\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1643s) >> I mean, it would basically be the same one as where's basically the same one as this one, but [\[28:09\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1689s) Right. >> Okay. >> And we probably name it to >> black surrounds two cells maybe. Yeah. >> Or black territory is two cells, spans two cells. I'm not sure. >> I think the guy called it connection. One black connection. >> I if I looked at this test, I don't understand that. >> One black [\[28:40\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1720s) Chain surrounds two cells. >> Okay, that looks good. This is called a chain I guess. >> Well, and I like that we see that it's already failing, >> right? But this one is like I just like we mentioned it cop this one does both the getting the winner and checking the group. So actually maybe it's not this test that >> Yeah, but what's the problem? I mean I'm trying to understand why do you have a problem with this test? [\[29:12\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1752s) Why is that bad? I feel like it's two two things we're doing at once. I don't know. Maybe you can show me why it's good. >> So, the way I think about it, it's not a bad test. Can you bring it to the screen? >> Okay. Where did I put it? >> Yeah, >> I just missed it. >> So, why do I think this is actually not a bad test? Because the way I think about it, a [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") only has three types of results. [End results](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)"). [\[29:43\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1783s) It either returns a value, it changes the state of the system, or it calls a third party, which is where you would use a [mock object](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") like to to check that a logger was called. >> Mhm. >> Now, in this case, we're filling the board. We're actually changing the state of the game. >> Right? Now if we were to check the state of the game the internal state we would actually be checking implementation detail which we don't care about. [\[30:14\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1814s) >> Let's say that we would check and we would check that and see that somehow the game knows that the two cells are surrounded. Okay. >> Mhm. >> It wouldn't mean anything because the get winner would not change behavior. Mhm. >> It only means something if it matters to get winner. >> So >> when I create the board, I want to get the result at the same scope at the same level where I change the state. I don't want to dig deeper. I want the entire thing to be encapsulated. [\[30:46\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1846s) So I don't care about how the winner is determined. I just know that the only thing different is and now now I have two cells. I don't care how it's calculated. I just know that it affects the winner. Okay. >> There is only one way to know that the game cares about this and that's currently by getting the winner. >> Mhm. >> Does that make sense? >> Right. >> Or maybe you're just being polite. I'm not sure. >> No, it makes sense. It makes sense. >> Okay. >> but if you if you can think of a different way to check that it knows about that these two cells are surrounded, I'd love to know. [\[31:23\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1883s) We can make a discussion. I just figure out one one of the tests we had is it eats up a white stone with when we surround it with black, right? So like this one. So if we have this one, we can do basically the same thing where we put in another copy of this cell. I mean copy of this test. >> Yeah. So these are two features we need to test for. I mean we need these two tests definitely. That's another behavior. [\[31:54\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1914s) >> Those are two end results that and each one of them needs a separate test or two features. >> One of them is eating the thing you just surrounded and the other is determining the winner. >> Mhm. >> Okay. Just because you eat something doesn't mean that the winner will still be determined correctly. Right. >> Right. >> So, we still have to check both of them. So, if that's what you meant, I understand that that's another type of end result. That's cool. Right. I was thinking that maybe this test might be easier >> than the other test. Like you know how you're you're talking about write the easiest test first. [\[32:28\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1948s) >> Sure. >> So >> why do you think it would be easier? >> I don't I don't know just I guess I guess it kind of like separating the steps from >> okay >> finding a group and getting a winner. >> Okay. So, so let's create a version of this test that you're currently selecting and comment out of the other one. >> Okay. >> Actually, it's a version of the other one only there are there are two whites inside the black chain. [\[33:01\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=1981s) >> What did I just do? >> Did I make a copy? >> I have >> I don't know. The window's so small. Okay. What's going on? Well, you can make the window bigger for now and just double click it. [\[33:34\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2014s) Okay, here it goes. Surround two. Round two. Opposite color stones. Two. Round two. Yep. opposite color stones, black, white, and white. >> Okay. And what about the other test? >> The other test we should probably >> need to comment out because it's we have two failing tests right now, >> right? [\[34:06\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2046s) >> Where did I put >> where? There it is. There you are. Our >> Okay. Okay. >> So, this test obviously fails. That's good. So, we should be getting the boarded position. I think the assert >> should probably change, right? So the the question for this one would be, should I I know like you don't like having two asserts, but would it be good to have two asserts to assert that both of these >> are empty? [\[34:38\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2078s) I think so. For now, it would make sense. And maybe later I might split it. But they're both about the same. They're on the same object. >> Mhm. >> So, I wouldn't mind. So, status two like this, status one, and status too. >> I think you got rid of the position status. [\[35:12\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2112s) Okay. Still failing. >> Mhm. That's expected. Okay. So, having said that, that doesn't work. So how do you want to work on this? So currently what's failing is [\[35:43\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2143s) The whole is surrounded by Right. >> Right. >> where's the thing that makes things empty? We need to later extract that. Right. It's always happening when someone changes the position. Yeah. And remove if needed. >> Stone is surrounded. That's what we care about, right? >> Mhm. So he's fully surrounded by. So we can check he's fully surrounded by maybe fully surrounded by might also check that. [\[36:22\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2182s) Okay. So what would be the simplest thing that would make that pass? I'm kind of wondering what would be a good way to solve that. >> I don't I don't know what the simplest way would be. >> okay. What's a good way? >> So, the way I did it was that I I don't think I don't know if it's a good way or not, but I basically found all the connecting stones and then I check and then I then I checked if those if those stones were fully surrounded [\[36:54\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2214s) >> all the connecting stones. >> Right? So if we go back >> like a recursive function or something. >> For me, I didn't use a recursive function. I I don't think it was necessary to be a recursive function. >> But for now, let's make an assumption that we just need to check the stone to the right. >> Yeah. >> Okay. >> And then see where we we we go with that. So, we can check is fully surrounded by and if it's not fully surrounded [\[37:28\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2248s) >> or or if it if it has a stone of the same color on the right. >> Mhm. >> interesting. What if we said it's not surrounded by but it's surrounded by except just one block of the same color. I think that would make the test pass. Yes. [\[38:00\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2280s) Yeah. And then we can introduce tests afterwards that makes it fail. Okay. So, I'm not sure I did what I just said, but I think it was smart or stupid or simple. We can check not just fully surrounded by but we can also check something like this var fully surrounded except [\[38:31\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2311s) One matching color We still have an assumption here about the color. >> Is our test about white or is it about black that's being surrounded? >> Right now it's it's black being surrounded by white. That's we haven't had we haven't added tests to remove that assumption yet. [\[39:12\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2352s) Maybe we should do that test first. >> Okay, sure. >> To remove the white assumption. Okay. >> so delete the whole thing. >> Comment out that test. >> Yep. >> Okay. >> H, that's not good. That's not what I meant. There we go. So this is the test that's failing. And this is the one that I'm going to comment out. [\[39:45\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2385s) Because our assumption that's not meant our assumption where is its assumption using Vim keyboard shortcuts here for some reason. Come on F and this is what it looks like. Seriously. [\[40:21\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2421s) White. Oh. Okay. So, what would a test that proves that we can't always choose white? >> So, basically, choose one of those tests and basically which one? >> that one right there. And then switch invert their colors. Okay. So, add stone surround opposite color stone color color stone. [\[40:59\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2459s) Actually, what if we not duplicate it but use the test case here? >> Oh, yeah. So instead we would do something like this test let's extract ah no we can't because the board is different we can put that actually we can we can create the string as an attribute string as well [\[41:34\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2494s) Like this then we could say that this is a test. [\[42:11\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2531s) And we would actually let's select it like this. Control control select would have worked here. I'm not sure why that's not working. Or maybe it's alt. Yeah, it's alt. There you go. And we would select the winner to be >> well this one isn't selecting winner is just >> empty position actually. >> Yeah. So it's still still the same. So you just need to copy the test case and convert to colors. [\[42:45\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2565s) >> Okay. And then we would say string board. Then we say that fill board with >> you already have a board variable. >> Yeah, board map. >> That sounds great. >> yeah, that's the same test. And then we'll just say B W B. [\[43:19\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2599s) >> Okay. So in this case empty position but was filled position. >> Mhm. Because the white was not removed. >> BBWB. Okay. It would have been nicer if NCrunch would have said this one failed and this one passed. >> Mhm. That's true. >> Okay. Now we can go back and say, [\[44:05\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2645s) I remember there was being a recursive lookout lookup. I can't remember what that key. Or maybe it's control I white. Yep, control I. In any case, >> the easiest solution would just duplicate it, right? And just change it to black, right? >> Here. >> Yeah. It's full surrounded. It's full surrounded by color white. [\[44:35\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2675s) I would say an ore actually. >> Or nice. >> Okay. So we would say >> Yep. >> Yeah, that makes it pass. >> But I got I got a test case for you that will make it fail. >> Yeah. Hold on. Let's just make sure. [\[45:13\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2713s) Yep. >> So if you have a black stone surrounded by all black that will that that will fail. >> Cool. So why don't you create that and that but it should Yeah. But it should not I mean that's a different test case. >> Yeah it's a different test case. >> A different expected behavior. >> Right. >> So okay. So, >> so how do we deal with that one? >> We create a new test because the name wouldn't fit, >> right? [\[45:46\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2746s) >> Unless we can actually, you know, what we could do? >> Mhm. >> We can also create a test case that just we can extract the empty and say we're looking for stone color empty here we're looking for stone color black >> fill. >> And actually, let's make it. [\[46:16\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2776s) >> No, it's position. It's position position fill >> position is always sorry >> because the assert is using position status. It's not using >> Yeah. Oh, so we should get rid of that empty thing. Oh, that's bad. [\[46:51\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2811s) >> I think we can get rid of position status later on. >> Let's make everything pass. Position status filled. So, let's make it white. >> Yeah. We you need to add the variable. You have it. >> Oh yeah, that's right. Status expected. [\[47:33\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2853s) Surrounded. position status one failing. It's this one. Let's make sure. Yeah, it's still white. Okay. [\[48:10\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2890s) >> that's a good test. So, how would you solve it? >> So, I would get I would have a a statement that chooses the surrounded color based off what the current color is. >> Why don't you go ahead and do that? >> All right. simplest thing that could possibly work. Remember [\[48:47\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2927s) XY Nice. Keep this one. [\[49:28\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=2968s) Yay. Cool. Okay, now we just need to make this much much more readable. So now we can do basically right? >> Yep. [\[50:04\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3004s) So we could say if it's surrounded by opposite color >> yeah I like to rename them. Yeah I I like it. >> I don't know if we need to rename it though. >> Okay. >> Surrounded can only be by opposite color. >> Yeah. >> I I was thinking maybe it needs to call another one but maybe not. I think the only thing if want to do is if you want to rename the method. [\[50:34\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3034s) So, but I think it's it's a good name for the method. >> Is there any other assumptions we have to get rid of here that we don't like? >> I actually wrote down a bunch of assumptions. So, >> where are they? >> Give me a sec. >> Well, there was in the to-dos. How do you u view the to-dos easily? I forgot. There's a there should be a way to >> control I todo. Control I >> todo. >> Oh. All right. So that one we did. [\[51:04\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3064s) >> Okay. >> So control L. Okay. >> Control shift L. >> Control shift L. All right. Control I again. >> Yeah. Incremental search. When no one owns any territories, the last player wins. The player that wins is white because of komi. We already removed that. >> We only already have komi, don't we? >> Yeah. Yeah, you're right. [\[51:38\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3098s) >> Actually, first round of territory found by the for loop is the winner. We remove that as well. >> Yep. >> I think that's it. >> What happens when you're out of board position? Oh yeah, like if you add add a stone outside of 1919. But right now we don't check we don't have it's like a new feature. We don't have anything about >> I don't think it's important now. I mean I usually try to when I drive new stuff I like to try to get the happy path first. [\[52:10\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3130s) Just get things running and then check all the edge cases and valid stuff >> because otherwise you can go through a whole day of just checking invalid stuff and then your man manager comes to you and says hey got anything for me and you'll say well I have nothing but it checks all the invalid values right so we never want to do that >> just leave it for now >> sorry >> we can just leave that for now we can Okay. [\[52:42\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3162s) >> all right. >> It's interesting. We don't even have the line of the top line. Have you noticed? Oh, yeah, we do, actually. >> The the line is offset by one, by the way. You need to add a space before the one. >> Sorry. >> So, let me add it for you. >> I don't understand. Oh yeah, [\[53:18\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3198s) >> that's just for readability though, >> right? >> So we have to go like this, >> what else? What else? What else? >> So we have the two features that we commented out. test for two features. >> Okay, let's go ahead with that. But you know what? Let me just let me just commit something first. What what feature did we just finish? >> so we just removed assumption [\[53:49\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3229s) That surround surrounded only by white. >> Removed assumption that surrounding color is always white. Anything else? Oh, added counting how many cells. Edit counting how many cells determine [\[54:23\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3263s) Determine the winner cells H1 H to determine the winner. Okay. Yeah. Okay. >> Okay. >> Cool. >> Okay. So, what test is should we uncomment first? >> This one you said was easier or No, you had an easier >> I think it's easier, but I thought it was easier, but maybe the >> No, this is not this is Yeah, >> this is harder. [\[54:54\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3294s) You think it's harder? >> Oh, no. No. I I I misunderstood. Yeah, I think this one might be easier, but I'm not sure. So this should fail right now. >> Yeah. >> And again the feature is surround two opposite color stones. Remove the opposite color stone. Okay. So we got rid of the thing here. So now let's see if we can make this work in a simple way. [\[55:31\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3331s) We got the opposite color is fully surrounded by the opposite color. We'll actually return false, right? >> Because but we also have a special rule that says aha but this time we can also be partially surrounded. >> Right. So we can check what if we had something like this are [\[56:03\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3363s) Part of a s might be part of a surrounded of multiple surrounded cells. is a adjacent with an A. Is it with an A? >> Yeah, I think so. >> Is adjacent cell [\[56:33\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3393s) Of same. Well, how would you name this method that that checks that we have? Well, for now the assumption is is that we have one cell of the same color next to us. Cell of the same color. H would you say that? That would be good. >> Yeah. >> So I would do something like this. And also [\[57:06\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3426s) Rules is almost fully surrounded. What do you think? >> so why why is there two have to occur right? First you have to have you have to be almost surrounded and the one next to you should be of your own color so it's not empty. >> I see. But I'm just I'm just thinking out loud. Maybe this is complicated. [\[57:36\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3456s) >> Can't the can't the other one be part of Can't this method be part of this method inside there? >> Well, it could be almost fully surrounded and the cell next to me might be empty. >> Or am I thinking too much about this? Maybe I should make that assumption. >> Yeah, maybe. Yeah, let's just get rid of it and then we can add remove that assumption about the empty later. [\[58:09\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3489s) >> What do you think around it? >> But if we want to remove that assumption, we could also do it in this method so that it it returns. >> Sorry, >> I think that maybe we can probably do it inside this method that in is fully surrounded by >> Yeah, but that would be we would start doing counts. I I want to right now >> just see if we can solve it without touching anything else. >> Okay. >> And then we can after it passes we can incorporate it by refactoring. [\[58:44\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3524s) Is almost fully surrounded. Int X int color opposite color. Okay. So it would almost look the same. Where is fully surrounded? Where does that exist? Yeah. [\[59:14\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3554s) So imagine we did exactly this. >> Mhm. Actually yeah, let's say surroundings don't [\[59:54\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3594s) But here we would check. >> well if you want to make it pass, you just >> comment out the one of them, right? >> You would just want to comment out one of them, huh? >> If we want to make it pass right right away. >> No, we would have to change it. Right? because that would pass for everything else that's for the surround to check the the other the get opposite [\[1:00:26\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3626s) Like so for us is surrounded on right we can just say is get opposite color we don't have to get opposite here that sucks we have to get it from board right so now we have to go here actually you know go with the board. [\[1:01:36\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3696s) So stone color matrix is basically what is it just get stone color? Yeah. Bor that get stone color. And yeah, I'm thinking we're diving here quite fast. Let's see. [\[1:02:06\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3726s) I'm kind of losing myself. It's a bit late. Let's see. So now where were what were we trying to do again? >> You were trying you we we didn't have access to a method get get opposite color but I think it's >> he's almost fully surrounded. Yeah. >> Right. Oh, and we said get opposite color of >> XY. [\[1:02:37\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3757s) >> X and Y. >> No, actually get opposite color of you wanted to get >> X and Y + one. Yeah, >> actually you didn't need to get opposite color. You can just get get current color of XY. >> That's true. Oh, that's stupid of me. or get stone color. >> Yeah. >> X plus Y. [\[1:03:12\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3792s) >> your your method return type is void. You need to be change it to bool. >> Yep. And we still have to go here and say rules. What else? Pretty sure it's not building. Let's see. Oh, actually it does build. It's still failing. [\[1:03:43\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3823s) So, or I thought that would be the simplest thing to just check that it's surrounded and it's the same color on the right. >> I think it's because we're checking both of them, >> but we're not using the result. That's why. So, if we go here, >> it's almost fully surrounded. So, yeah, we get almost surrounded, but we don't return anything. and we don't do anything about it. [\[1:04:13\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3853s) >> Mhm. >> So, >> so if >> so if fully surrounded no problem. But let's say we can say if almost surrounded then both positions are empty. So x + one. Right. >> Right. Okay. I see. [\[1:05:01\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3901s) But it's still failing. So, that's not working. is >> your code is checking on the right like what what can you dive into is almost fully surrounded. >> Okay. >> Oh, it's y + one. Maybe that's the problem. No, it's it's the top one. [\[1:05:32\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3932s) Is that mean the second one? >> Oh, yeah. So, it's X plus one. So, it seems like it would work. And we can just say put a break point and test with debugger. That sucks. I think I'm trying to think if we could have made a smaller step, but I think we're cheating quite enough. [\[1:06:02\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3962s) Anyway, run on right. We have X and Y. >> Surround on left is already false. What was the X and Y right now? 30. >> Yeah, we should wait for surround on left to be true. True. >> Okay. >> Oh, you're red. Okay. So now we have x4 and y1. x4 and y is one. [\[1:06:33\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=3993s) So that shouldn't be get surrounded. >> Yeah, that's not it. We were looking for 22 x2 y2. So you could put in conditional x2 y2. >> That's true. But we already got there. >> Okay. So now we would have >> so left checking that board gets stone color of x + one is the same as board stone color of xy >> right but surrounded on left is already false [\[1:07:22\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4042s) Shift. There was a shortcut for that, I'm pretty sure. Shift P. No. Control Shift Damn it. Debug. Quick watch. Shift F9. That's value empty. Interesting. It's an empty color of x minus one. Are we getting the wrong board here? [\[1:07:52\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4072s) >> I think you might have removed it. >> You think we already removed it? >> Yeah, like maybe the code that we added somehow removed it. >> I don't know how though, but at least we found the bot. like so it's almost fully surrounded. Oh, so you think in the fill board? >> No, I mean in this is almost fully surrounded. [\[1:08:23\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4103s) Maybe it returned true when checking W and then removed it. Maybe it's possible. Oh, because we already added the code here. [\[1:08:57\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4137s) So, we got here before we got here. So, we haven't removed anything. >> Okay. But we did get almost surrounded. So, that's good. >> So, that's for 41. X41. So then it removes >> x4 and >> and then >> one >> plus one. So that should be on our right. Okay. >> That doesn't make sense, right? Am I missing something? [\[1:09:28\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4168s) >> I mean it's this position. >> Oh, I think No, I shouldn't. >> What? >> No, I was wrong. I was thinking of I was thinking that maybe I mean it should have well actually you could check the board position right now but I'm guessing that when it checks this one it it says it's surrounded and then it removes this and it removes this [\[1:09:59\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4199s) Because it doesn't check. Let's see. So two one is empty and one and one two one and two one and one two two one Damn it. Two one is empty. Yeah. [\[1:10:34\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4234s) >> Yeah. Because it's it's checking for freely surrounded even if it's empty. >> Mhm. >> So we shouldn't make anything if it's empty. Make sense? >> Yeah. >> So if something is empty, it can never be surrounded. >> No, but the thing is >> that makes sense. >> Yeah. Yeah, you're right. You might not add that to is almost fully surrounded only though because the almost fully surrounded is kind of interesting where I mean it's kind of >> fully surrounded has the same problem. [\[1:11:05\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4265s) >> But it's fully surrounded only removes >> in that middle position. So if it's empty it'll set it to is empty. >> Yeah. >> The almost fully surrounded is if it it's also setting what's right of it. So we can just the simplest thing would be to just check if board get stone color of x and y [\[1:11:42\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4302s) Equals empty >> right >> return false. Okay, so we had here here >> and now we can try again. Obviously still failing. [\[1:12:17\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4337s) I wonder if the viewers at home are already lost or not. So, now we get here first. And that's okay. What was the XY? 32. Okay. >> 32. [\[1:13:03\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4383s) So, status one. Okay. So, three and two should not say that it's fully surrounded. Should say it's partially surrounded, right? >> Yeah. So >> no, it's not this one. It's this one. So 32, but we had two and two that also came out fully surrounded. Right. >> Right. So I I think I know understand what's happening. So [\[1:13:34\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4414s) It's it's first checking here and then I mean when it adds this actually no I don't really understand. Oh, when it adds the W maybe right here and then it checks then it checks this one first. >> Mhm. >> And then or if or maybe it might be No, actually maybe this one. I'm not sure which when when is it which stone is it adding that it does the remove stone. [\[1:14:06\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4446s) Do you know what I mean? That's why I'm just trying I'm just trying to understand how this code is working. >> I think if we move fully surrounded to be first and will win. I mean basically if we do this it will help some way and the reason is because this returns true as well. [\[1:14:40\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4480s) >> Mhm. >> So we want to get this one first but that didn't help. Was more of a guess actually. [\[1:15:12\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4512s) What if we just did this? We have to fix fully surrounded. That's what I think. What do you think? Are you Are you Are you lost as well? >> you should not say fully surrounded successfully. That's what I'm saying. We have a bug here. Do you agree? >> If if it's empty, you mean if it's >> I mean for 3.2, it should not say that it's fully surrounded, >> right? >> Do you agree? >> I agree. I agree. Yeah. >> Why did it say it's fully surrounded? That's what I'm That's why I'm asking. [\[1:15:43\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4543s) >> So, you want to dive into that then? Yeah Fully surrounded. So we will check here. Let's try again. [\[1:16:15\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4575s) Okay. So here we have x and y of three and two. So now we can go ahead and start debugging. Why does it say that's fully surrounded around on left says true wtf dude get stone color surrounding stone color is white. [\[1:16:47\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4607s) And here x is three, y is two. So we have two and two. It says that this is actually white. >> Let's see. Board position stone color. [\[1:17:19\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4639s) Two and two. This says white. Oh, I think yeah, I think that remember we I think we have an unfinished business. We only check if something is surrounded if if the first three if it's surrounded on top, left, and bottom. >> Mhm. >> I think [\[1:17:52\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4672s) And when we added this one or this one or one of them, it already checked and turned it into white. >> No, it doesn't not supposed to turn anything into white. It's supposed to make it empty. >> True. >> So, what the hell? >> Yeah, I want to check first if it's always white or was it black and somehow it turned into white. >> Okay. >> so how we do that? [\[1:18:25\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4705s) >> You bug the hell out of this. So right now the board position before doing anything is [\[1:19:05\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4745s) And we have the stone color matrix. Everything's empty except we have white at two and two. >> See this? >> Yeah. >> So, can we set a break point at adding when we add the stones to the board? here. >> Yeah. And then run the test from the beginning. [\[1:19:42\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4782s) >> Okay. >> So 31 is right. And then we should >> Okay. 32 black. Yeah, that's right. Three is white. Okay. 42. Oh, he didn't start from the beginning though, right? So, we don't know >> it didn't start from the beginning. I'm not sure why [\[1:20:16\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4816s) >> two and two white. >> Okay. So, we came here from here. So, we always add a white here. >> Oh, I see. Wait, what? How does that How's that part of the test? >> Am I getting a wrong test? >> You're in the wrong test right now. We're We're trying to do [\[1:20:51\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4851s) That's a different test. >> What the hell? Hello Mike. Okay, >> thanks world. >> It's problem with the font too big. >> All right, >> let's make sure we're not crazy. >> So much for TDD, huh? >> so we have So let's just make this a bit bigger so you can see it. [\[1:21:35\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4895s) >> One and three is white. >> Yeah. One. And that's it. So this is where things happen. One and one becomes empty. Okay. >> Okay. >> Two and three black. [\[1:22:12\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4932s) >> Two and four white. >> Okay. This is this is probably where No, actually no. Probably the >> Why is two and four white? I think we might have accidentally switched the X and Y positions. I mean, it's like two, four. It's supposed to be two, four in our fillboard. We might have accidentally switched the X and Y positions. [\[1:22:46\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=4966s) Please, how but how how do all the tests continue to pass then? cuz the it didn't really matter which direction is X and which direction is is Y. It's mainly for readability. So you could like just rotate the board and it's still the same, right? >> But it's not. >> You >> But it's not. You think it's because that we have different length on and X and Y? [\[1:23:21\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=5001s) Say again. I'm not sure I understand. >> So you think X and Y because they have different length then something's wrong. I mean here I and J. Okay. I is the line. Let's rename that. Okay. >> No. So if you switch Yeah. >> We add the line number. I think I think the I was the Y and J was the X because you're going through each each line like up like that and then you're going >> Let me change line number to to X. Okay. [\[1:23:51\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=5031s) >> Okay. >> And X. So we X and Y and J is the line length. Aha. So J is actually X. Yeah, that's what that's what I meant. >> That should be Y and then the other one should be X. Jesus X Y [\[1:24:35\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=5075s) Tests passing. All tests are passing now. So it's the original reason was that. Nice. Our fill board was wrong. >> Oh my god. This is this is why this is why I always recommend people not to have any logic in the tests because that's the hardest crap to find. And here I am doing such a rookie mistake. Horrible. I'm just If I had any balls, I would ship myself right now. [\[1:25:09\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=5109s) Horrible. Oh god. Okay, I'm going to commit this and go to sleep and just just just think about all the things I could have done with my time. Git commit to say we are so stupid found some bugs in our tests like Oops. And what did we actually add? [\[1:25:40\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=5140s) What feature did we just add by the way? We had how do you say check >> two neighboring positions if surrounded by opposite stone? >> Yeah. >> or check >> multiple stones can be surrounded but only on the right. >> Yeah. Only attached on the right. >> Perfect. [\[1:26:12\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=5172s) You know what? As far as I'm concerned, this is an achievement based on our current stupidity level. >> Okay. >> All right. >> Okay. So, thank you for an amazing session, Raymond. Seriously, that was that was just chalk full of awesome. I will see you maybe tomorrow. >> Yeah, >> go away color scheme. Okay. See you see you dear viewers. [\[1:26:42\]](https://www.youtube.com/watch?v=OTgudmmPuGY&t=5202s) Hopefully you won't want to shoot us for this. >> Cheers. Dear God, ## Related - [A buggy test gives a false failure](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_137) · The Art of Unit Testing, 3rd ed., ch. 7 Book section on a buggy test giving a false failure, like the line-break and X/Y swap bugs in the test helper. - [Testing the test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2) · The Art of Unit Testing, 3rd ed., ch. 2 Book section on testing the test, the same move as planting a bug to prove the new test can fail. - [How can we know we don’t have bugs in our tests?](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11) · The Art of Unit Testing, 3rd ed., ch. 11 Book section answering how we know we don't have bugs in our tests, the core lesson of this session. - [Tests should reflect required reality](https://osherove.com/blog/2005/4/5/tests-should-reflect-required-reality.html) · osherove.com On making a test fail first for a meaningful reason, not an illogical one, as the pair check the counting test. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [How to know you trust a test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134), ch. 7 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19), ch. 1 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 #### The Art of Unit Testing, 2nd ed. - [Building a test API for your application](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6), ch. 7 #### osherove.com - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) [Previous lesson Finding a Winner](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/finding-a-winner/) [Next lesson A DSL for our Tests](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/a-dsl-for-our-tests/) --- title: "A DSL for our Tests" url: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/a-dsl-for-our-tests.md" canonical: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/a-dsl-for-our-tests/" tags: [] author: "Roy Osherove" description: "Lesson 7 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 55:07. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # A DSL for our Tests 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD Pairing Sessions - Building a Go Game](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/) 3. The Sessions Lesson 7 of 11 Duration: 55:07 [Watch on YouTube](https://www.youtube.com/watch?v=TGTnFqtIWQ0) ## In this lesson In session five the pair turn on NCrunch, which runs the tests when the code changes and shows [line coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)"). For counting territories they write tests where one color owns one cell and the other two, but the tests pass unexpectedly and they cannot find out why. They build a [DSL](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6 "Building a test API for your application (The Art of Unit Testing, 2nd ed., ch. 7)") that draws the board as a string with numbered rows and B and W stones, parsed by splitting and trimming lines, and convert the other tests to it. ## Transcript 5,375 words [\[00:03\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=3s) Hey Raymond, how are you? >> I'm doing great. And >> welcome to session number five, I think. >> Yeah. >> Cool. >> So last session we actually stopped with a dilemma about refactoring and we did some refactoring for strategies. But then we we figured maybe it wasn't a good idea based on the fact that we were going to do scoring. So let's see where where this takes us now. So [\[00:33\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=33s) We stopped short. Let's make sure that all our tests are running. Can you can can you press Alt R? See what happens. I wasn't sure how we had run it last time, so I'll just run it this way. >> All right. >> Okay. And also you've installed NCrunch, >> right? I haven't tried it yet though. >> Okay, so let's try to enable it. Enable NCrunch. And there's this wizard here. [\[01:05\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=65s) Now, I tried NCrunch a bit on my machine. It's a pretty cool thing, but this dialogue when you try to enable it is just horrible for newbies. So this is how many cores it should use. Max number of background processing threads. Optimize for fast test execution. Run test in parallel. No for us. No. Which again engine execution mode automatically when changes are detected. You see how many questions now? [\[01:36\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=96s) Ignore test. Ignore all my tests by default. No. I want to run all of them for now. And that's it. So that's that's how easy it is to get started because you really need to know what you're doing. But once you get started, it's a pretty cool thing. So right now it's running test in a separate threads and 14 tests are being monitored and let's see maybe we should put it here. [\[02:13\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=133s) I'm not sure what would be a good good clip here. We'll see. What if we just here maybe we don't need it. I'm not sure. But anyway, now you can see the [coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)") which line is being covered. And you don't even have to press save for the tests to run. So that's pretty cool. So if I if I return like this basically already [\[02:50\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=170s) Tries to run the tests when it detects some code changes. So if I say equals equals here just to make a bug, you can see that it says project failed to build. So that doesn't make sense. and we didn't even have to do anything and now it's running all the tests again. So if you wanted to see the status we would say NCrunch risk and progress bar [\[03:22\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=202s) And that's what I used. So it says okay basically so that's what you care about the most. So if we say small equals you can see that status immediately changes and that didn't break anything. But if we say big bigger than [\[03:53\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=233s) We have nine failing tests. Pretty cool right? >> Right. Very cool. Okay. So, what else do we want to do now? So, you want to can can we try to remember what feature are we working on? >> So, we're working on counting the territories. We have not implemented counting getting points yet. >> Yeah. Right. Now we have a feature that says the winner is the first person who that we find that has any kind of territory. [\[04:30\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=270s) Right. >> Right. Right. >> So now what is the [simplest test](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") to prove that this assumption is wrong? So we can do it where the we can make it so that we can start introducing the concept of of how many territories each person owns. >> Sure. So we can like make the first the first territory that would be found owned by one person that only owns one territory and then the and for the other player would make it like they own two territories. [\[05:09\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=309s) >> So it should fail because it'll find the first one which is incorrect, right? >> Crap. >> And we should be it should be fine. Instead it should be returning the one that was two territories. Okay. Okay. So, we're going to have two players and one of them going to have two territories. One of them is going to have one territory and the one with two is going to win, right? >> Yes. >> Okay. And that test should fail first. >> Yep. >> Okay. Cool. Okay. So, you want to try and write that? [\[05:41\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=341s) >> Yeah. Black owns one cell, white owns two cells. Expect white win. [\[06:13\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=373s) >> Okay. Right. So, oops. >> So, I was thinking we might also want to make u like a [DSL](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6 "Building a test API for your application (The Art of Unit Testing, 2nd ed., ch. 7)") for describing the board. So, for example, you know what? Write the test first and then we'll see if a DSL would help us here. [\[08:13\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=493s) Okay. So this is 2 three. This should be four six So we're not making two consecutive cells for why we're just making two separate territories. [\[08:46\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=526s) >> Because right now we we have our code does not handle two consecutive cells. >> Sure. >> Okay. >> Right now our our code only handles finding for one cell at a time. >> Okay. >> So that would be another feature we need to add. >> Mhm. I think it's written in the Excel file. So, >> but this is not failing. >> Is not failing. >> No, you can see all the green, right? [\[09:21\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=561s) My guess is is because it still takes the last player as the winner by default if it needs to. If we add a black player play at the end that doesn't do anything, I think it will fail. [\[09:59\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=599s) >> Oh, >> interesting. >> Interesting. So, our test is wrong. something wrong with our test. What if we just did that for a second? Okay, so we have the board. We have a black territory in the top two and two, three in one, four and two, three and three. [\[10:43\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=643s) >> So the second one is X, right? Just to make sure. >> The second one is Say again. >> The second parameter is >> Yeah, second parameter is X. The The third one should be Y. >> Oh, but I Okay, so this is X. This is Y. Okay. So that's three, that's two, these are three, all these are four. Interesting. [\[11:14\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=674s) Why did it say that? Like maybe maybe our code is amazing. >> Let me comment this out first. Make sure it return should be returning black. Okay. >> Interesting. >> So, you see when they both have when they both have one, the white one, it tends to win. [\[11:45\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=705s) So, maybe we should reverse it. Maybe we should have two black points so that the black should win. [\[12:17\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=737s) >> Okay. >> But you still assert that the white wins. Ah. Crap. We're just too Maybe our code already takes care of it. >> Interesting. >> you want to debug it and see what happens? >> Yeah, let's do that. Let's do that. >> Hold on. Hold on. Can you add Let's uncomment this one as well. [\[12:48\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=768s) >> Okay. >> Make it white just to make sure. Okay. Yep. That doesn't make any sense. Cool. Okay. So, let's see what if we made a break point here. [\[13:26\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=806s) I feel this NCrunch is making everything run slower. >> Really? >> Just my opinion. >> Okay. >> anyways, hold on. Hold on. >> Oh, okay. >> Let's continue. >> Okay. >> So, what happened? >> we're breaking in right now. >> Sure. >> We're debugging. >> So, I'm jumping in. Jumping in. >> jump in. Probably jump in. [\[13:58\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=838s) Okay. I would just say if the first cell what it returns. I don't think we need to jump in. Let's just debug the outside and see where the bad result is. >> All right. So, result is black, >> which should be right. because we did that. >> Sure. >> And then what happens? >> And the result is not equal to return result. Okay. So that's the reason why it wins. Let me >> So why does the white one [\[14:31\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=871s) >> win, >> right? >> Because the first level >> interesting. >> We should u we should switch this with this so that white is first. Right. So that way. >> Why? >> Oh, but it returns white. You said it returns white. So maybe we should >> No, I'm saying that it did return black. Our ours is on black. But when we when Let's create another test the exact opposite test just like we did before. [\[15:04\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=904s) And we'll see that it returns white in the in the opposite test. So, >> you mean like what we wrote before, what we wrote earlier? >> Yeah. Hold on. >> Sorry. >> so we should like change it back to what it was before. >> No, no. I'm saying let's let's make a copy of the test and make it opposite. >> So, make sure that we're testing it from both sides. >> Okay. [\[15:36\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=936s) >> I did not rename the >> Yeah. So let's rename the previous one to black wins. >> Black owns owns one cell, two cells, one cell. Black win. Ah, this is unfortunate. [\[16:17\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=977s) Just copy the test the text from the middle text from the other test and then it it won't reformat right. I try to make it bigger. >> Yeah. [\[17:01\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1021s) You think this is fine or should I switch all of them? >> Well, the assert is wrong. All right. So, we have two whites and one black territory. >> But this might return because of the I know I should have switched the bottom one >> because it's the first one. It should be it's the first one with the cell wins. Right. [\[17:31\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1051s) >> Right. So the first one should be black and then this one should be white and then they should fail. It's not failing. Interesting. Okay. Obviously we're just we just too good. No, I'm going to I'm going to run it through the [test runner](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_37 "The library, the assert, the runner, and the reporter (The Art of Unit Testing, 3rd ed., ch. 2)"). [\[18:04\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1084s) I don't believe this NCrunch, dude. What did it say? 15 pass. >> You know what? Let's since >> I forgot to add the test part to it. >> Sorry. That's why. >> I think it should be okay. >> Okay. It's crazy. All right. >> Okay. Hold on. I I have an idea. Since everything's passing, let's what if we could write a test this way? [\[18:35\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1115s) Control D with DSL. Okay. Just to make this variation. What I wish we could do is to write the same test. >> Mhm. >> this way. Fill board with [\[19:16\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1156s) Let's fly like this. would have 1 2 3 4 5 6 7 8 9 10. What's the minimum column number? 12 11. >> The minimum well we Yeah. Minimum is nine right now. >> And you go. The minimum is nine. Yeah. [\[19:47\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1187s) >> Okay. And then we have two, four, five, six, seven, eight, nine. >> I think you still need the one. >> Really? >> Oh, yeah. >> Yeah, I forgot. Cool. >> Yeah. >> And then we would have let's say empty. >> You could type out empty for the whole thing. Well, what I want is for not empty to be white. You know what I mean? [\[20:18\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1218s) So, this would be oh, so you think it should be like this? It would have a white. What the hell is going on? Why is it not letting me write? Oh, because we don't have space. We have white. [\[20:53\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1253s) >> Does that make sense, >> right? >> Maybe we shouldn't use the commas here. I'm not sure. >> yeah, >> sure. Let's not use them. [\[21:29\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1289s) Like this. >> Yeah, looks good to me. So we can have this and then we could have black here. Okay. Yeah. And another black. Like this. [\[22:07\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1327s) Then another two spaces. No. >> No. This one only has one. Oh, sorry. I messed you up. >> Dude, this is delicate work. >> By the way, the the test you're writing in is black owns one cell, white owns two cells. >> Yeah. >> So, this is like for the other test. Oh, the other we can copy and change it. The big problem here is the empty spaces. >> What do you think? Is this more readable? >> This is more readable. [\[22:37\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1357s) I agree with that. >> Yeah, >> it should be pretty easy to to to generate the board based on that, don't you think? >> I think it should be right. >> Do we even need these numbers though? Am I naked? >> I don't know. >> What if we just did this? >> and then >> I think the n I think the numbers make it more readable. [\[23:09\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1389s) >> Yeah. >> But we're going to have a problem when we reach twodigit numbers. >> Uhuh. >> But in that case, we might just repeat start from zero and one. You know answer like >> one zero 1 2 3 4 5 6 7 >> I agree I agree with that. That that sounds good to me. >> Okay. So let let's start try to create that. [\[23:40\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1420s) Okay. >> Okay. Well, we don't want to make sure the Oh, I guess the tests are passing. >> Yeah. So where is board? >> Oh, now it's Oh, you >> Wait, wait, wait. Map stone map. Okay, so this would be like basically a loop, right? [\[24:11\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1451s) Right. >> Or int i equal but we would start from one right >> right >> up to >> which is still zero >> h >> yeah but we would need to we don't care about the numbers we just care about the >> you understand what I mean the inner loops we just care about what's after the numbers. So but here we'll start with nine. So it would be until 10 [\[24:45\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1485s) And we reduce from one >> right then there's another inner loop from 10 to one. So like the the simplest stupidest code we could think of just just to to generate this code. So it would be >> I think this is actually you just board add stone and then if >> but >> if if not empty. [\[25:24\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1524s) >> Yeah. Just just if so we just need to get the string first. Right. >> Right. String s equals stone map. Oh, how do we treat the stone map? Uhhuh. In this way, we we didn't we didn't figure that. Maybe we'll just create it as an array. >> Array would be easy. Yeah, >> but less less readable. [\[25:56\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1556s) But I'm pretty sure we can just calculate the the position right based on I and J, >> right? Yeah, it might be easier to just get the line and then where there is a W or a B. So instead of like instead of like so instead of a for loop inside a for loop you just get for each line and then you get for each letter starting from one. [\[26:26\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1586s) >> Yeah but how do you get the lines? How do you split it by line? >> >> for based on new line >> yeah I mean because it's actually I don't know if there's a string method to do that. split. Just split by line. >> Right. >> Yeah. And for each >> for four, I think we need a four to to get the line number. [\[26:58\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1618s) >> Oh, yeah. We don't know what what the line number is. >> Yeah. >> Do lines. >> do lines count counts. >> Sure. Sure. >> And starting from one >> really Oh yeah, that's true. >> I think count is a capital C where it's size. >> I think it's length. >> Okay, here length, right? Okay. And in that case, we would have [\[27:30\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1650s) You start you can start from one until the end of that line array. the so I guess you would write line equals lines I yeah string line I and then we would do basically a >> another for loop yeah >> to line length [\[28:02\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1682s) >> right it's starting starting from one because you want to skip the numbers on the side. >> Sure. >> And then it would just be you check if if it's empty first. >> Why don't you give it a try? >> Okay. >> I think it will be faster. >> So get it get the string I guess. >> Yeah, the string. So I I would say it's I don't know how I call it cell equals [\[28:35\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1715s) Line J, right? >> Sure. >> How come it's doesn't care? Okay, even easier. Oops. Okay. Okay. If cell not equals space [\[29:08\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1748s) And just if cell equals Ah, what was that? Just Yeah, we need the board. We need to give it the board object. >> Oh, yeah. You're right. [\[30:26\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1826s) >> does that look right to you? >> Well, there's something doesn't compile here. >> Yeah, we need a parameter here. >> Oh, yeah. Maybe we should make board first. >> Sure. >> Might make it look nicer. there. >> Okay, now we just need to remove the other ones. [\[30:59\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1859s) I mean this whole >> this whole thing. I mean this. >> Okay, now it's failing. >> So, what the hell? Maybe we typed in something wrong. >> You know what we should do? We should Well, well, the the assert is you said that this board is actually matches the other test. >> Oh, yeah. You're right. So, this should be black. [\[31:30\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1890s) >> So, so yeah. So it should be like this. Wait, I guess we could just replace all. No, just just Oh, come on. Black like this. Black. I think that's easier. [\[32:02\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1922s) White. [\[32:33\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1953s) All right. Still failing. >> So, you know what we need to do? We need to put this in a in an existing passing test that we know that we [trust](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134 "How to know you trust a test (The Art of Unit Testing, 3rd ed., ch. 7)"). Mhm. >> So we see if we break existing tests. >> Okay. >> So what are some simple tests we can the simplest test we can we can think of here maybe like this. >> Yeah. [\[33:08\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=1988s) So we would have a black at number two. Right. Okay. >> And number one, >> delete everything else. True. Oh, I think I know what the problem is. I think we don't have the full lines at number four and five and six. So, maybe that doesn't I think the loops are are all wrong. >> Really? Yeah. [\[33:40\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2020s) >> I mean I feel like it would need >> I mean you see that I mean I mean it it fails because >> the strings end I mean the I and J end here. You can see that. >> So >> it looks like this test is passing right? >> No it fails now. Oh you Oh yeah I thought that this Yeah because we still doing it right here. >> Okay. Yeah, we can re remove that >> at least one cell one for black, right? So, we should remove that. [\[34:15\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2055s) >> Okay. >> So, this means the other test is failing, right? It's not this test that's failing. >> Well, I guess we can see that exactly by going to the tests >> the DSL. Okay. Okay. >> What do you think? >> I think it looks good. I think we should jump into the to the other tests and figure out why it's failing. [\[34:46\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2086s) >> Okay. Maybe supposed to fail. >> Actually, I want to know why the other one test is passing. But >> well, let's let's replace this one as well. >> Okay. >> I think it will not pass now as well. Okay, nice. Is there something wrong with our hands still? Maybe. Hopefully. [\[35:16\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2116s) Okay. So, I'm still scared that our DSL is wrong. So, let Why don't we replace all the other tests with the DSL? >> Okay. You want to comment these two tests out so we can see green? Yeah. Yeah, sure. Yes, that's a good idea. >> You want to keep it to the board? >> Yeah. So, [\[35:52\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2152s) >> we're green. >> Yay. >> Everything works. >> Okay. I think it will be faster if you do it on your end. >> All right. So it really fast. It just copied from the simple tests. >> All right. Where who was that? Simple tests. Okay. So this one is get position status. Nope. It's not. >> Yeah. But we can we can say that there is no board. Oh, maybe not. Sure. But here would be good. >> Yeah. So this one was >> one and one. [\[36:24\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2184s) >> I should I should have deleted first. And just one one. So be this one. Should I just comment it out for now? >> No, just delete it. We have source control, right? >> yeah, right. Okay, >> cool. >> This one's the same one as that. it's green. Oh, it's red. Oh, what did I do? [\[36:56\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2216s) Hold on. A board get what? What? What? What did you replace? >> One one. >> No, there was one two. Okay. Yeah, it's the same board, but the get to position status is now different. Okay. So, okay. Replace it. Okay. >> Now, it fails. >> Okay. So, let's find the problem here. You want to debug it? >> Yeah. [\[37:27\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2247s) >> Okay. >> So, all right. Where are we? Okay. I want to see the status of board first. [\[37:57\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2277s) Empty one one should be filled. Everything else is filled. One, two, one. Everything else it's saying is filled. So, yeah. So, let's go to the fill board. So, okay. Okay. So, what's the best way to look at this? Should add another break point in here until it's one, two. It's going to be No, let's just let's just start see what happens. [\[38:41\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2321s) So, one one should sell. Oh, it's because if there is no >> the cell is currently wrong. The cell it means one. So it it doesn't treat the one cells. The cell is a number. Cell is a number. >> Yeah. Look at the cell. You see it's right here, >> right? It's starting at one though. [\[39:12\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2352s) What's the line? A line is Oh, it's looking at the How come this How come line is what? What's lines supposed to be >> first one? It starts at starts at one because we have a empty. We have a new line right here. >> Which new line we have? >> No. Which which new line do we have? Oh, this one. >> Yeah. >> Okay. So, we should always do what do you call it? [\[39:44\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2384s) Trim on the string first. What do you call it? Trim or >> there's a function that removes all the all the extra stuff, all the extra spaces. >> All the extra Okay. >> from both sides. So, I think it's called trim. So, the way you do it is stone map equals mount dot trim. [\[40:16\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2416s) Yeah, that's it. All right, let's try. No, I don't think it gets rid of empty lines. >> only it gets rid of all the spaces at the beginning and at the end, >> right? But the problem we're having is that empty line on the first on the first line. Right. >> Yeah. But that would have been trimmed. That's what I'm saying that if we put a break point here. [\[40:46\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2446s) >> Yeah. Okay. >> Oops. >> Ah. Okay. You want to try and repeat that or let's see. Okay. >> Yeah. So, if you look at the stone map, there's still a dash end in the front. >> Oh, wait. We need to look into that. >> No, no, hold on. [\[41:16\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2476s) Step to the next level. To the next step. >> Okay. >> Okay. So, you're right. It is trimmed. Okay. >> So now let's let's see what happens. Split by line. >> I think we should split by slash r/n maybe. Ah you're right. So this one should be right. Okay. So then one two. [\[41:54\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2514s) This was sona. Yeah, you're right. - dash r. Okay. So, so we just slash r. So, we should split by slash r first, right? >> Okay. >> And then for each line, we would just say line i.trim. And that way you see now it passes. I didn't have to debug. [\[42:25\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2545s) >> Nice. >> But I still went to debugging before I noticed. >>. >> All right. >> Okay. >> Cool. >> So now what if we uncomment the last test that was we're were passing when we expected them to fail. >> Okay. Just this one. [\[42:57\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2577s) H. Okay. What about the the one just before? Can you do it? >> Okay. >> So, this one this one might be failing for the right reason. Maybe we don't have that feature. So we don't know. So let's replace all the other tests. >> So see what happens. >> No, I think this one we the winner should be black. [\[43:27\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2607s) >> Some reason we have it white. >> But your [test name](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html "Naming standards for unit tests (osherove.com)") is wrong in that. >> Well, this one's two blacks. Oh, one. Yeah, this one was this one was a copy of this one. >> And we didn't. And then >> Yeah, we we replaced the wrong test. Remember, you made a copy of this one and added DSL to it. But I never replaced the original the the one that should have been replaced. >> Yeah. So, this one's supposed to replace this one up here. [\[43:58\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2638s) So, >> wait. But but this is the one that fails. >> Right. So, let's get this. Let's get rid of this one. This one's exact copy of the of the bottom one right here. >> Hold on. Yeah. I've got the phone fix anything while I was on the phone. >> No, I didn't. [\[44:28\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2668s) >> Okay, cool. >> So, we should probably delete this one cuz it's a duplicate of the >> Are you sure? I thought it was the the the opposite of the one that was >> was that was green, >> right? So, now they're all passing right now. So we should I kind of want to look into I want to kind of dive into this and see. >> So these two tests we didn't expect them to pass. Right. >> Right. >> Did we replace but all the other tests? >> we have not replaced the other tests yet. >> So I think look because because I I have to finish soon. [\[45:01\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2701s) So let why don't we finish up by fixing all the other tests with the DSL. >> Okay. >> And then we're going to have to finish for today. Maybe we'll continue at night but I really have to go and pack. >> Okay. No worries. Okay. So, let's replace the all the other test DSLs. Let's make sure we're on the right track and we'll have a good infrastructure to to run the test later. >> It's mindboggling for me though. Why it's not mindboggling, it's frustrating for me. >> It is mindboggling. [\[45:31\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2731s) >> It's interesting. Why is it not passing? But this one should be >> She wants one white. >> Oh, how are we going to do the stuff where >> where what >> we >> where we don't because right now it's adding the stones. Well, I guess this is more like a setup. >> It's basically Yeah, it's set. How are we going to do what? >> So, like I'll show you in the next one. [\[46:02\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2762s) Let me make sure this passing. Okay, so this one actually is not this one. Like this one right here. This test right here. So, >> sure. What's the problem? >> Well, I guess we just don't we don't >> we don't care. >> We don't I don't replace this bottom one right here. The one I highlighted, right? >> No, but here's the cool thing. You can use fill board three times. All it does is just sets sets up the locations, right? >> Oh, yeah. [\[46:33\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2793s) >> So, you can >> That is cool. >> Yeah. So I can >> but would it would it make sense? >> I know. I think this is readable. So we can add one to two and two. >> I what what I'm saying is it's more readable if you just say add board after that. Add stone instead of two fill boards >> like this. >> Yeah. >> Actually, I think I might have written it incorrectly. [\[47:04\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2824s) Sorry about that. >> so we have a Yeah. >> Yeah. I do this incorrectly. One, three. So, it's white right here. Black, two, three, and white and then white right here. So, >> isn't it so much more readable now? >> It is. I like and it's so it's easier to write. [\[47:36\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2856s) >> So this is what they meant by DSL on one of your guys comments. >> Sure. >> So >> I don't think we don't we even need to go up to nine. We can just use like up to five >> because it only fills whatever it cares about. >> You want me So I should do that. >> No, I'm just saying that for the future test we can just make it >> Oh, for the future, right? >> Or just remove the past rows. Oh, I didn't need to do that. [\[48:13\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2893s) >> Yeah, you can just remove rows six to nine here and that's it. >> Yeah. >> Control shift L. >> Sorry, >> I can do that. Let me cop this one. [\[48:47\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2927s) Nice. I I think it's Yeah, I think it's nice this way. Hold on. I think that's the last one, right? Oh, no. We still have one more. Okay. >> Yeah. Got a little bit left. [\[49:21\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2961s) >> I think it will actually work because we do trim even if you tap the the string more to the right. So, it will be more into the middle of the code. I can try that. >> Yeah. >> How how far should I put it? >> Just after I think just after the at sign. >> Okay. >> Yeah. >> I think that's more readable. What do you think? >> I think so, too. >> Okay. [\[49:59\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=2999s) Hold on. Don't touch anything. >> I guess this NCrunch is pretty cool. >> Yeah, I kind of like it after the initial annoying setup. It's pretty cool. Yeah, I haven't pressed saved yet, so that's a little bit bothersome. I don't know if it's automatically saving for me. [\[50:29\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=3029s) >> Obviously, otherwise you couldn't run tests. Looks even prettier than before. >> Very cool. [\[51:44\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=3104s) I should remember black 31. All right, I think that's all of it. Nice. Time to commit. Let me tap this. F. [\[52:22\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=3142s) What happened? That's not nice. [\[52:59\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=3179s) >> Are you getting close? >> Almost done. >> Almost. I'm just tabbing these things here, dear. Don't worry. >> No, it's really important. You see, honey. >> All right, cool. >> Now we're done. >> All right, save it. Commit. >> Can you do it on so Yeah, so viewers can see. Cool. [\[53:39\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=3219s) Should I remove the in front project? I'll just check it for now. >> Sure. So added DSL for about not sure why tests are passing. Last two tests are passing. >> Yeah. >> Cool. >> Cool. All right. Very cool. [\[54:09\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=3249s) >> Okay. Where's Where's my push? There you go. Okay, Raymond. Let's do let's do another one, I guess, tomorrow. No, no, tomorrow. Yeah, maybe tomorrow. We'll see what happens. But maybe tonight. So, cool. Hopefully that was that was informative to to the viewers as well. It's mindboggling because I'm sure I did the same test and it failed when I did it. [\[54:45\]](https://www.youtube.com/watch?v=TGTnFqtIWQ0&t=3285s) I don't know. Maybe I skipped this step. >> I don't know why it's passing out. I'm kind of I'm probably going to dive into it right after and see why. >> So, if you have any any insights later, we can we can talk about them in the future episode. >> Okay, >> cool. See you, Raymond. See you, viewers. >> Thank you. ## Related - [Building a test API for your application](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6) · The Art of Unit Testing, 2nd ed., ch. 7 Book section on building a test API for your application, which is what the string board DSL becomes. - [Writing readable tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 8 Book section on writing readable tests, the goal behind drawing the board as text with B and W stones. - [The role of helper frameworks in your tests](https://osherove.com/blog/2005/1/15/the-role-of-helper-frameworks-in-your-tests.html) · osherove.com On test helpers that replace object-creation clutter in growing tests, like the board-parsing helper built here. - [Smelling a false sense of trust in passing tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7) · The Art of Unit Testing, 3rd ed., ch. 7 Book section on smelling false trust in passing tests, as the territory tests pass unexpectedly and puzzle the pair. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [The library, the assert, the runner, and the reporter](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_37), ch. 2 - [How to know you trust a test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134), ch. 7 #### osherove.com - [Test Coverage and testing angles](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html) - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) - [Naming standards for unit tests](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html) [Previous lesson Total Noob Fail](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/total-noob-fail/) [Next lesson A Refactoring Dillemma](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/a-refactoring-dillemma/) --- title: "A Refactoring Dillemma" url: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/a-refactoring-dillemma.md" canonical: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/a-refactoring-dillemma/" tags: [] author: "Roy Osherove" description: "Lesson 8 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 43:47. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # A Refactoring Dillemma 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD Pairing Sessions - Building a Go Game](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/) 3. The Sessions Lesson 8 of 11 Duration: 43:47 [Watch on YouTube](https://www.youtube.com/watch?v=X2F5Dn8wiM4) ## In this lesson In session four the pair use Mighty Moose, a free Visual Studio plugin that runs affected tests on save, and start replacing the komi mode check with the strategy pattern. Komi and first cell winner strategies inherit from a winner finding strategy base class that gets the board in its constructor, and the komi flag and current winner field go. The change breaks the test where white should win by komi when nobody owns a cell, raising the dilemma of whether counting points will replace the strategies. ## Transcript 4,179 words [\[00:04\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=4s) Hello everyone and welcome to session number four. Raymond, how are you? >> I'm doing great. >> Cool. So actually, you know, I've been thinking a lot about our code and I'm not really really really happy with it. Although we've definitely made progress, I'm not happy with the design that's slowly emerging. I don't think we're refactoring enough. I don't think the code is is nice enough and maintainable enough as it is. Although it does work, but just the fact that it's working doesn't mean that we should leave it the way it leave it the way it is. [\[00:39\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=39s) By the way, we've also installed Mighty Moose just to see how things are going. And so far it looks pretty cool. So every time we're going to save, it's going to run all the affected tests in the background. And it's a free plugin for Visual Studio. It's pretty amazing. So, for example, you can see here the number 12. It means there are 12 tests covering this method right there and they're all passing. There are 14 tests with board [\[01:12\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=72s) Cuz 14 tests create board. But I'll tell you what I'm unhappy about. What I'm unhappy about is basically the rules class. specifically there is this in komi mode right there. >> Mhm. >> and this does bother me. I mean this little if thing that's usually a sign that we can we can get rid of it by refactoring to some sort of either a strategy or some sort of chain of responsibility any kind of polymorphism here really would work. [\[01:48\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=108s) Are you familiar with the strategy pattern? >> A little bit, but I'm not sure how a strategy would be used here. >> Okay, so the way I'm thinking about this is that the get winner there are currently two strategy strategies or actually three for determining for determining the winner. There is the komi mode strategy. Okay. And that strategy is only should only be active when no moves have been made yet. [\[02:21\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=141s) Okay? >> Right? >> And then there is another strategy where moves have been made and and you just look for whoever won some some cells so far, >> right? >> And the third strategy is the last player, >> Okay. and and right now all these three strategies are in the get winner method. So they all work but they're definitely not separated. So the [single responsibility principle](https://osherove.com/blog/2013/3/6/refactoring-string-calculator-with-solid-principles-in-mind.html "Refactoring String Calculator with SOLID Principles in Mind - Examples Needed (osherove.com)") definitely doesn't apply here. [\[02:53\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=173s) >> Okay, >> does that make sense? >> Right? >> So the way I think about it is that what we can do is we can slowly refactor this into three strategies and then decide where these strategies get get applied. For example, I would create a class. I would basically copy this whole thing. [\[03:24\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=204s) Create a class here. We can move it later. Class komi komi winner strategy. Okay. And that it will inherit from a find winner finding strategy. [\[04:04\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=244s) And all it has is a public stone color get winner. >> H. Okay. >> and it takes in a board. And this is all the code that this komi strategy will have since there is no if. It's always white when we're in komi. [\[04:34\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=274s) Right. >> Mhm. >> Right. >> and so this code will end up being just for now I'm just refactoring. I will say a new actually no I will say [\[05:07\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=307s) Winning yeah new komi control alt space maybe nope That doesn't work for me. That on a map that doesn't work well. Control space. Damn it. Komi winner strategy. Get winner. This [\[05:37\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=337s) Actually bored. Okay, obviously this doesn't compile yet. We just need to create the base class here. >> create class. Yeah. And we can make this method abstract. [\[06:08\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=368s) Just just make sure first of all let's see what happens. Okay, ran successfully. Six test pass. Okay. >> Okay. >> so we didn't break anything yet. But now I'm just going to refactor this and say pull members up or is it down for the base class? I think it's I think it's up. [\[06:38\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=398s) Let's see. >> So now this method will have to be in each winning strategy. And let's save. Okay. Now the strategy has an abstract class. Now it's overriding an abstract class method here. [\[07:08\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=428s) >> And I'm thinking that it probably just needs the the board in the in the constructor instead. What do you think? yeah. So we can say is there a No, there is no. So we can say [\[07:40\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=460s) Public winner finding strategy or B. Am I missing something? Semicolon. >> but it's not abstract. It's just a constructor. Okay. >> Oh, I see. >> in which case we would just use introduce initialize field B. [\[08:17\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=497s) And let's not make it private. We just want to make it protected. So, we can use it in the base class. Mhm. >> Then get winner doesn't need a board B. It just uses it if it needs it. Okay. >> why do I Oh, yeah. Okay. Let's see what happens. Well, I'm not initializing it correctly now. So, [\[09:02\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=542s) Hm. Oh, did I miss that in the Yeah, I missed it in the base class. So, create a constructor. awesome. Now everything should pass again. And it didn't. >> Correct. >> It did. Okay, [\[09:35\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=575s) Cool. Like I like it every time I save that the test run. Isn't it cool? >> It is cool. >> Okay, so after we factor for the three the the three strategies, we could use like a factory method that determines which strategy to use right now. >> Okay. >> Okay. Or or B we we might not even need this the the the factory mode but let's see let's just see where it leads us. Now this whole thing [\[10:07\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=607s) >> is one strategy right? >> Mhm. >> So what we're going to do we're going to factor this We'll create another class [\[10:37\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=637s) Class. First cell winner strategy which is a winner finding strategy. What else? Create a constructor. H. >> Oh, that wasn't what I meant. [\[11:20\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=680s) And implement members and it needs the rules. >> Sorry. It needs reference to the rules rules object >> actually is fully surrounded by >> either it needs reference to the rules object or it can just we can just move fully surrounded by here. >> Mhm. >> What do you think? [\[11:51\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=711s) >> Okay. Yeah, >> we can we'll copy it for now and then we'll see if we can get rid of it. >> I see. Yeah. >> Now, where is it? Why is it not complaining about board? Interesting. Oh, because that's a stat. That's a const. Okay, that's pretty cool. So right now we're just saying this is fully surrounded by [\[12:26\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=746s) Like this. And I'm I'm definitely doing this incrementally because I'm changing a lot of stuff. So, I want to make sure I don't break anything. Now, here's the cool thing. Change all board to [\[12:59\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=779s) Nice. Okay, let's see what happens. Oh, it's not going to compile yet. Still have a problem here. Yeah, I have one extra. Why is it undo? If public override, this is the public method for int. Oh, we still have to return something, right? >> Mhm. [\[13:41\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=821s) >> what do you recommend? >> I recommend putting a variable that that we're going to return and then set it inside the if statements maybe. [\[14:15\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=855s) I think it's one above that above that bracket. >> Maybe you need You need to type explicitly. Okay. Sure. Let's make it nullable. Who cares? I just want everything to tell me everything is okay. [\[14:47\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=887s) Control S. I think what >> the return type >> oh it has to be a nullable as well. >> Interesting. Yeah, true. And stone color equals no let's set it to empty for now. Okay. >> To pass, right? >> Yeah. We can see that right here at the bottom. [\[15:18\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=918s) All right. It just mentioned six tests. I wasn't sure if it mentioned six tests passed or what. >> Well, it only runs the affected tests. >> Yeah. >> What's interesting is that it says that nothing actually used this one >> because we haven't refactored yet to use it. >> Isn't that cool? >> Yeah. >> so it's not really covered because we haven't refactored to use it. >> I see. So here [\[15:49\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=949s) We might say check if it's empty and then return. >> Well, the default is empty. I'm not sure. >> Well, you you for your function, if it did not find any, it would return empty. >> If it did not find any that are surrounded, it would be empty. >> True. pools. New first [\[16:19\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=979s) Strategy board get winner if result I'm used to reading now. That's why I use that or not equals [\[17:02\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1022s) Cool. Cool. Very cool. Why does this say it's still not covered yet? Interesting. >> I think it said that also for the auction. No, the komi winner says that. >> Let's just make sure. Okay. >> Yeah, we really didn't break anything. So that's not making them really comfortable for now. [\[17:32\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1052s) >> But the other one was Oh, that was updated. Maybe it just takes a while. I guess >> doing doing in the background. >> Cool. Five me it's yellow risk analysis 44. That's great. Thanks. Okay, so now we almost have all the strategies we need, I think. The current winner is always the last one, right? >> Mhm. [\[18:07\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1087s) Where is that being set? Let's see. Control Alt F7. It's always a notify stone added. >> Mhm. >> Okay. So I think what we would do in this case is we would have like default winner strategy, >> right? Okay. >> Or like a like a hard-coded winner strategy in a way, >> right? >> [\[18:39\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1119s) What I mean is >> Yeah, like a hard-coded winner strategy every time the last one wins. That's possible, >> you know. If we switch if we switch the two strategies around, >> I think we can get rid of the current winner because the reason we had the current winner was because yeah, but I want to get rid of it last. I want first of all to just replace the current thing because then we would do too many things at the same time. [\[19:11\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1151s) >> Okay? >> So, I want to replace the existing structure and then maybe remove some of it. >> Okay? Because the point here is to do it things incrementally. It's part of the exercise as well. But are you saying we could get rid of the whole thing? We don't need a default one. >> Yeah. If if we switch the komi and the fully surrounded part. So let me take over. >> Sure. >> If we where's the two strategies part? [\[19:47\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1187s) >> it's above just above at the top. Yeah. >> Okay. >> It's so short now that it's hard to define. >> Yeah. >> I think if we move this my control X okay to here >> and replace >> and I think we could return we can remove this one >> and then you don't need >> actually. No, you're right. It won't never mind. You're right. We still need it because the the komi would be false. You're right. [\[20:19\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1219s) Actually this might you might even remove the in komi then I think you can get rid of the in komi the if and komi part and then remove the yeah and try running that >> yeah interesting >> that's nice >> let's make drawer. [\[20:50\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1250s) >> Sweet. Now I like this better. >> Oh, cool. Okay. That went nice. So now, now we have to decide I still want to get rid of those ifs cuz we shouldn't need them. >> Okay. Right. Now the way I think about it is that [\[21:30\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1290s) Hold on. Let's just make sure. Let's get rid of everything. We don't need in komi mode. We don't need current winner anymore. Let's see. Building projects. And [\[22:00\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1320s) Okay, cool. Now we've ran for tests. Actually, we don't need a notify stone added right now anyway. >> Yeah, >> that's pretty cool. But let's leave it for now. We still need to decide what to do, how to get rid of those ifs. And also, I'm going to get I'm going to move these away. Just move to outer scope. [\[22:36\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1356s) Will not be accessible then I will make it accessible dude Yeah, that's not going to work. We have to make that let's move that as well. move to another file because we need that in the file anyway. [\[23:13\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1393s) Make it public. what did what does that say? Oops. I think it has to do with the fact that we haven't moved those inms here. I don't know. I'm not sure. [\[23:47\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1427s) Move that. >> No, I think the one of them is not public. the the komi strategy is not public. Is that the reason why? >> Could be. Let's see. Komi strategy. >> yeah, this will tell us exactly rules. [\[24:26\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1466s) Hold on. Call me >> No, but ReSharper also is kind of smart. So, it's telling us cannot access private >> private constants. >> Just make it >> because you moved it out of the class, right? >> Sure. >> So, >> okay. Save everything. [\[25:01\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1501s) Okay. Now let's continue. Just move those things away. Move to another file. What's going on? >> So, I think every time you move the file, it does all the mapping over again. [\[25:35\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1535s) >> Mhm. >> That's why it's taking a while. >> Well, it doesn't say any test tra. So, what I'm going to do, I'm going to just press alt R. 14 pass. That was faster. And then we have the board again. What else? What did I do? Double click. No, that's not what I meant. Like this. [\[26:05\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1565s) No. Let me just make sure I'm putting all everything I need. Okay. We have the board. We have still the komi winner strategy. So let's get rid of that. Function F6 move to another type. [\[26:38\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1598s) Actually what I meant is move to another scope. It's awesome. And again file [\[27:10\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1630s) Cool. And I'm going to press Alt R just to make sure as well. I'm not sure it helps me if I keep running alt R as well. What does that mean? I wonder bookmark navigate with control 2. Okay. Okay. So now things might start to look a bit more more reasonable if we look at the structure. So what what what I'm going to do is is I'm going to do create a [\[27:49\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1669s) Nope, I'm going to do this here. Add there should be an add folder. >> Yeah, I think it might be. Is that one? >> That's the window for you. >> Okay. >> so we call that find winner finding strategies. [\[28:20\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1700s) And then basically we have winner. Just move that over here. First cell winner. And here, just to make sure, let's save everything. Okay, cool. So, I think it's beginning to look a bit more interesting now. >> Mhm. >> Any thoughts so far? [\[28:52\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1732s) >> I think it's looking better. >> Yeah. >> Okay. >> No way, Team Explorer. No one wants you. Okay. So now let's let's see how we can get rid of these ifs. So one way to get rid of ifs is to is to basically do again polymorphism. That well in in this case I'm not sure [\[29:23\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1763s) Actually because it's not a flag at the class level. If it was at the class level, I would say well, we have rules komi rules and we have non-komi rules basically, >> right? >> But in this case, I am not sure. Maybe in this case we we might say just go through all the rules and if the first one that returns a non- empty would work. [\[29:59\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1799s) >> Yeah. >> What do you think? >> Yeah. But how would that work? That still sounds like there's still a logical if there. >> but but this but this way the first rule the rules get to decide if they return something or not. So the logic is not in the loop. Okay, >> because a rule gets to decide, well, I'm the one that should be applied now, >> basically. >> And if I and if I don't matter, it just returns stone color empty. [\[30:30\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1830s) >> Mhm. >> What do you think? >> Yeah. >> so that's one way to think about it. Another another way is to is to get a like a a factory method for the rules for the winner strategy. Mhm. >> but we still have to see if one of them actually has worked. >> so we wanted to get rid of the komi flag. Right. >> Right. >> So right now we just wanted to re refactor. [\[31:02\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1862s) >> So here's here's here's another way that is something that I've I've done in past projects. We can have a fa a field that says public winner finding strategy winner finder. Okay. >> Mhm. >> Equals null. >> I see. I see. And in notify we would basically say that the winner finder [\[31:32\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1892s) Equals new first cell winner strategy. >> Wow. >> in board and but by default I'm sure we have a constructor here, right? >> Right. >> Do we? Yeah. No, we don't. >> no, I'm not sure. So by so actually we can just default it to new komi winner strategy [\[32:04\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1924s) In board. >> Wow, that's pretty interesting. That's pretty cool. >> Actually, that won't work because board hasn't been assigned yet. So we do need a constructor. Alt insert. Can you run alt insert on your end? >> Yeah, constructor. Yeah. With do we need board? Yeah. We'll do we'll do board later. For now, just just you just just press enter. [\[32:37\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1957s) And now the basic rule is that winner finder by default equals new winner strategy. [\[33:13\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=1993s) Just to make sure we would just say here return Now we just need to replace the calls to a new board. >> You need to change it to null. First this part right here. Which part? >> Here. >> True. >> There you go. >> Okay. And one last fix is is new rules [\[33:44\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2024s) With this. 12. >> That's awesome. What just happened? We went from nothing to [\[34:16\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2056s) Cool. Let's see. What the hell happened? Let's see. >> I think maybe right click might tell give you more information. >> Yep. Okay. Or not. >> No. No. Forgot what they said. Oh, it say D. D. What does D say? >> I. You just click I and I guess. >> Okay. I >> [\[34:54\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2094s) Message object reference not not send instance of an object. So we get a null here at some point. Okay. You know what? I'm going to run the the TestDriven.NET for now because it's easier for me to understand what's going on. >> this is where we're getting a null. Mhm. and add stone. [\[35:25\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2125s) Check stones and remove if needed. What's null here? Let's see. >> I think the only thing that could be null is the board, right? It's passing a null board. >> Oh, yeah. because we're not initializing it in the constructor. Yeah, we we definitely have a bug is that the rules is not setting the board. It's just it's just using it. So >> board [\[36:04\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2164s) >> interesting. So black doesn't own Okay. Termin winner. Black doesn't own any cell but played once. White should win by komi but we actually got empty. Interesting. That's because [\[36:35\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2195s) >> I guess that's because we had before it passed because of actually no I don't know that's a little weird because it should be the logic should be the same as before right >> so in that case what we can do is go back to the place where we changed most of it and say instead of just get winner, we can go back and say return you call me. [\[37:10\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2230s) Oh, it's it's because yeah, because we had it by empty. Now, before we we would use the komi if the result was empty, but now we're not using the komi result at all. The komi winning finding strategy, >> are we not? >> It didn't get away. It get it didn't get rid of the >> the what? >> Didn't get rid of If it returns empty, >> but it used to work. That's that's my thing is that we broke it and I'm not sure why. If you're sure why, I'd love to see how you'd fix it. [\[37:42\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2262s) >> Umh, >> but for now, I'm just gonna say >> how we fix it. So, the thing the reason we moved it down here Oh, >> yeah. Sorry. >> Is the reason why we set it right here is because we thought, oh, we don't need the komi anymore. But what we had before was >> Yeah, sure. >> If before we had was if result equals empty, right? >> Oh, yeah. And so the bug is that komi might still apply even if there was a play. >> Right. [\[38:12\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2292s) >> Right. It's right. Komi applies even if there's a play if there was no if nobody owns any positions. So yep. Okay. That that's okay. So that's the bug is that we shouldn't have just applied komi by default and then it's never going to be used again. I think the the easiest solution right now is to actually make something that makes sense where we actually just counted the [\[38:47\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2327s) Number of positions that are surrounded for each color and then add add to it and that would actually give the winner. >> Do you know what I mean? >> Sure. So, but in that case, so let's let's >> it kind of kills off the rest of what we done before though, the komi winner strategy and the first cell winner strategy. >> I'm not sure because I think later we're going to have different ways to determine the winner, right? [\[39:21\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2361s) Different strategies. Well, it's in the end the bas the only strategy you just well I guess the strategy could return the number of points and you just add the strategies together. So there would be a strategy for counting the number of >> remember you had the strategy for determining the winner either by points lost or by points won. >> Yeah. So yeah. So I mean the strategies basically return how many points based on each strategy [\[39:52\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2392s) I guess. Okay. So for now let's just let's do a loop and and we'll we'll get rid of it. You think we don't even need a loop? Cuz I just want to keep it that way for now. >> Well, we could do it inside the first first cell strategy. Oh Wrong one. Where did I do? Okay. We do inside here where we do the loop here. [\[40:23\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2423s) >> Mhm. >> And we just add it. >> Add what? >> So like >> but then we would remove the single responsibility principle, wouldn't it? Wouldn't we? >> Right. >> So I don't I I want to try and avoid that. Because then we've just moved the whole thing to just a different place, but it's still it's still the same ugly thing. You're saying that there can only be one strategy, right? [\[40:54\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2454s) >> Well, the strategy could be get this strategy. We could rename it to get number get points for white. get >> yeah but we don't have the need for points yet we need to have a test for that >> okay >> I want to I want to do this incrementally so that we can show a demo >> so for now so we can show a demo I I will just say var result [\[41:26\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2486s) New actually I'm going to undo yeah v result equals new first So when your strategy board get winner just like we did before. >> Mhm. >> And if result equals [\[42:05\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2525s) Return result. Okay. Turn you. Sure. Okay. We don't need this. And we don't need this. Okay. Let's make sure everything is passing. Okay. Now, let's commit. First let's so that we can do some commit the refactoring to source control. [\[42:50\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2570s) I forgot to git ignore. Okay, I'll do that later. >> Sure. Okay. >> okay. I think that's all the time I actually have right now. So, sorry to leave you hanging. >> no worries. >> But, we'll do we'll do more of these. [\[43:22\]](https://www.youtube.com/watch?v=X2F5Dn8wiM4&t=2602s) Okay. >> Okay. >> So, next time we're just going to add test to say Okay. Now, the winner has to be determined by counting actually, not just the first one. The first one to win. >> Okay. >> Okay. Ray, it was great. And I know time passes so quickly when we're doing this, isn't it? >> It does. >> Okay. Thanks everyone. >> See you later. >> All right. Bye. ## Related - [Making your tests withstand design and interface changes - remove code duplication](https://osherove.com/blog/2005/4/10/making-your-tests-withstand-design-and-interface-changes-rem.html) · osherove.com On keeping tests resilient through a redesign, relevant as the strategy-pattern change breaks the komi test. - [The test is out of date due to a change in functionality](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_138) · The Art of Unit Testing, 3rd ed., ch. 7 Book section on tests out of date due to changed functionality, the question raised by the broken komi test. - [Changes in the production code’s API](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_157) · The Art of Unit Testing, 3rd ed., ch. 8 Book section on test changes caused by production API changes, as strategies take the board in their constructor. ### Also linked in this lesson #### osherove.com - [Refactoring String Calculator with SOLID Principles in Mind - Examples Needed](https://osherove.com/blog/2013/3/6/refactoring-string-calculator-with-solid-principles-in-mind.html) [Previous lesson A DSL for our Tests](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/a-dsl-for-our-tests/) [Next lesson Debugging Excursions](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/debugging-excursions/) --- title: "Debugging Excursions" url: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/debugging-excursions.md" canonical: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/debugging-excursions/" tags: [] author: "Roy Osherove" description: "Lesson 9 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 51:29. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Debugging Excursions 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD Pairing Sessions - Building a Go Game](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/) 3. The Sessions Lesson 9 of 11 Duration: 51:29 [Watch on YouTube](https://www.youtube.com/watch?v=fgfPhEW6934) ## In this lesson In session seven a test fails on Raymond Lim's machine, and NCrunch [coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)") markers show the almost surrounded code never runs. Conditional breakpoints and moving stones away from the edge point to a bug near the edges, so they add tests near the top and left edges. Replacing the fill board call with add stone calls shows the bug is in the [DSL](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6 "Building a test API for your application (The Art of Unit Testing, 2nd ed., ch. 7)"), whose X and Y swap was never committed, and they start a check below the stone for vertical pairs. ## Transcript 5,452 words [\[00:06\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=6s) Okay. We're back. We're back with session number seven, I think. And this time, a special treat just for you viewers. We have the special video face of Raymond Lim. Please welcome Raymond. Yay. How are you? >> I'm doing great. >> So, let me just explain the situation. In the previous episode, we had a massive fail in that we did some really weird newbie stuff and our [DSL](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6 "Building a test API for your application (The Art of Unit Testing, 2nd ed., ch. 7)"), our tests actually had bugs. [\[00:40\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=40s) And in this session, Raymond has gotten the last version of the changes from git and we have another test that's failing, just one. And it probably has to do something with line ending. So, right now, Raymond is debugging to see what the hell the problem is cuz this test is passing on my local machine. So Raymond, any any progress yet so far? [\[01:11\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=71s) >> not really. It looks like it's adding it's reading it correctly and it's adding it correctly. This one. >> So, what's the test that's failing right now? Is it the one on the right? >> Yes. >> Is it? That's the last one we worked on. >> Yeah. >> Passes on my machine. >> Surround opposite color stones. Remove opposite color stone. >> Well, it passed on your machine after we updated the the DSL method. [\[01:42\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=102s) >> Yes. >> So, we didn't like verify if it actually passed or not. >> We didn't verify if it actually passed. >> Yeah. Because we didn't do the thing where we make sure it fails first and then pass afterwards. >> We were so tired. >> Yeah. >> But the test did pass. >> Yeah. The test looked like it passed. >> Actually, NCrunch told us that all the tests were passing. >> Yeah. >> On my machine. [\[02:14\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=134s) And right now, oh by the way, did you I I noticed something about the previous video and that in the beginning we NCrunch actually told us that some code was not covered and that is marked with the black dots. I mean if you if you look at the right I see >> you'll see that the second assert never gets executed. >> Right. That's because it fails on the first. Right. >> Exactly. Okay. And when we went to the DSL method, I was wondering why it showed that some of the the loop wasn't working because of the split that didn't work. [\[02:48\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=168s) And I if we had if we had listened to NCrunch more, we could have shown that there wasn't any [coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)") that it wasn't splitting correctly. So I'm wondering if you run everything now, we'll see what the coverage is before you we continue debugging. Maybe we'll have a better understanding. >> Okay. Just just debug to the end and see what happens. >> Oh. Oh, I already exited. Do you want to just run it with end cover? >> No, no, no. Just run it as usual and NCrunch will already let us know what's going on. [\[03:21\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=201s) >> Yes, the one failed right here. >> No, just run all of them. >> Yeah, I did. Run test, right? >> Yeah. And how many? Oh, I guess two videos. Okay. Maybe put it right here. Right here. No, right here. I'll have to find a good spot. Okay, here. Okay. So, this is the one that failed. [\[03:53\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=233s) Double click here. What happens? Okay. So, we can see the second assert never gets executed. Mhm. >> if we go to fill board, it does run. It just fails. So, it's not like it's not covered, right? >> You say, "What do you mean it's not covered?" >> I mean, it is covered because it's red. [\[04:23\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=263s) It's not black. >> If it was not covered, then it would be black here. Like last time when I saw it >> on my machine, >> this line was like red or green or something, but all the lines in the for loop were actually black >> on the on the dots, >> which means it never got got executed. >> Okay. >> But here I don't see anything like that. >> so I I thought maybe if we had looked at it this way, we would find out. [\[04:55\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=295s) So what does the test say? Actually, let's let's figure it out. Expected empty but was filled. Position status is empty and status one. So basically what we said is that if you fill out the two black cells and surround them correctly, they should be emptied out, right? [\[05:28\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=328s) Should probably should be two three. We're checking status of same one. >> Oh yeah, that we had that as well, but we never checked the we never checked the second one. >> Yeah. Anyways, yeah, so right now it's supposed to be empty but still filled. And if you set a break point right here, >> you run a test. [\[06:13\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=373s) >> I think we should just put a breakpoint on rules notify stone added and see when that that that that clears up the board. >> Right. I just wanted to show you that the the board matches what we expected right now. So, >> well, I can see a filled position right there. >> Right. It might be easier with from here. So, one, two, one, three, and then two, one, two, three, four, [\[06:44\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=404s) And then three, two, three, three. All right. So that's for the fill positions. And then for the one, two, one, three is white. And then you got a white, black, black, white. And you got white, white. So it is filling it properly. So we could re we should probably rerun the test. And you say remove stone is surrounded, right? Breakpoint. >> Okay. So let's rerun the test. [\[07:37\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=457s) Okay, so this is checking 30. Why is it checking three 0? should be checking three 0 anyways, but we're not looking at 30 >> because it's always checking the ones around something that was added as well, >> right? So, this one's checking 32. So, this is when it's which one is adding should we do continue? [\[08:09\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=489s) F5. We should wait until >> I'm kind of lost actually, so I'm not sure. Right. I was thinking about waiting until we add stone for this one. Two, three. >> Actually, you know what? Let me see if I can run the same all the tests on my machine again. You didn't change anything, right? >> I didn't change anything. Yeah. >> Okay. So, I'm just letting Visual Studio load on my machine for a second. [\[08:41\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=521s) And we'll see what happens if I run the tests. Do not recover. Okay, hold on. I'm going to miss the weather in Israel when I'm in Norway a bit. [\[09:12\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=552s) I can't say I'm going to miss all the sweat. >> Okay. Let's see if we can run all the tests. Just just run all the tests, right? Run tests. Well, surprise surprise. one is failing on my machine as well. >> Okay, so there's nothing wrong with my machine. So sometimes NCrunch doesn't get it all all right. [\[09:42\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=582s) Okay, >> interesting. So we didn't finish the job. >> Yep. >> What the hell? >> We were tired. >> Yeah, I guess. So >> Okay. Oh, according to So, we're working on this stuff right here. >> Yeah. I'm going to do one small thing and I'm going to increase the font size for a little bit. [\[10:14\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=614s) >> Okay. >> Let's see if that works. Nope. Can you press control scroll just to do like 10% bigger the font? >> Control scroll. >> Yeah. I mean, >> control and scroll with the mouse. >> Okay. >> Yeah, I think that's better. >> Okay, >> cool. >> Anyway, back to our problem. [\[10:46\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=646s) So, I guess we're just continuing the debugging session from last time. That sucks. >> I was thinking we might be actually be productive at some point. So this is our logic in test continuing to screw with us actually. What do you think? >> No, I think this is >> Hold on. Have you noticed that the the the there's all the black stuff that never gets executed? >> It should say almost surrounded. [\[11:25\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=685s) >> Okay. That was a treat that will not repeat. Yes. For the view, you'll see it later. You can't see the video right now. Anyway, so if you notice it, it it says almost surrounded is actually false. Can you see that? >> Right. >> I mean, do you see the black dots, >> right? I think it's for for the X for the XY 43. >> Yeah. But the point is it never for any stone gets the almost around it >> otherwise it would have been covered. [\[11:57\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=717s) Right. >> Right. >> So that's interesting. >> I mean if we can you just continue back. Let's see if it does get covered at some point. >> what did I just do? >> I think you exited debugging. >> Oh that's good. That's what I wanted to do. >> Okay. >> I was wondering if that that would work. Shift F5. >> so remove stony surround. Now you can see that the coverage [\[12:29\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=749s) Actually never get here. >> Why did some point and cover NCrunch tell me that everything was good. What the hell? What did I miss? So it says almost surrounded is actually always false. So that's the bug. >> Yeah. >> So last time we went to almost fully surrounded and we did a like a hardcoded thing. [\[13:05\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=785s) >> We checked basically the stone to the right. Agreed. >> All right. surrounded on right board minus edge or board gets stone color of X + one and the same Y equals the current stone color [\[13:47\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=827s) So I want to dive into when the ad stone reaches >> I think we should put a break point there in the in the almost fully surrounded on the right. >> almost >> just on that line that that checks hardcoded to the right. >> Okay, >> let's see what happens. >> Well, this one true. >> This one we actually put the break point here. Condition. I don't never really used this before. Is it x= 3 [\[14:17\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=857s) X = 2 >> equals equals >> equals = 2 2 and y = 2. Oops. >> So I I don't remember the syntax, but that could be it. >> That should be it, right? All right. So then if I take this out, should run it like this. [\[14:52\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=892s) Maybe take this out for now. All right, there we go. And then we can just step down. It's a two two surround color stone is white surround. And if we walk down Oh, what just happened? Let's get [\[15:29\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=929s) >> Okay. Oh, so >> right now it's empty. So maybe I need to run F5 again. I think it's still empty. Shoot. >> I think we're not running the correct test. Are you sure you this test? >> Oh, you might be right. I think I might have started running from the first test. All right, let me start over. [\[16:16\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=976s) All right, there a way for me to figure out what board is right now. if it's checking an empty cell or not. I'll just do it can just check it on the next if. Right. We're going to if you just step into the next statement, you're going to know if it's empty or not, >> right? [\[16:47\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1007s) Just still empty. Why is it empty on two and two? >> Because the first time you put it in, you check it put it right. The first time it checks it is when you enter W right here. And the next time it checks it is when you enter W right here. >> Okay. >> So now now this time is probably when it's right here. >> Okay. So if I if I do [\[17:18\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1038s) Yeah so on left surrounded on right is false. >> Yeah because we haven't added a second black stone I guess. >> Yeah it would be nice to know why. I guess I guess we should go down the stack, >> right? >> and say, "Oh, we don't we we don't need to be here. We need to be one above >> two three." So >> you need to break here when the stone we're adding is the last one on 33, [\[17:53\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1073s) >> I guess. Right. >> Which one is Yeah, I think the 33 gets added last here. >> Right. Okay. So, we should just run F5 again. No, I think we should put a like a break point >> right here. >> Only stops when X and Y are three and three. [\[18:28\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1108s) >> Was it this? >> I think now you can dis disable all the other way points. >> All right. Oh, this one's 33 right now. So, add stone 33. Notify stone added. It fills it up. Let's check the current stone matrix. So, >> that shouldn't be a problem. We have tests for that. >> Okay. >> The problem is the is the next one. >> All right. >> So, you should check [\[18:59\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1139s) It would be the one above. So y minus one. This should be this one. So this one's the one we look at. >> So for each zone, >> for each stone, we're checking if it's fully surrounded. Isn't that weird? Now maybe we don't need to do that anymore. >> For each position around the stone, I'm not sure. >> I think we still need it for now. I don't know what's the other alternative we have. >> Yeah, I can't that's just optimization for now. [\[19:31\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1171s) Okay, so now we've just added three and three. Now we're checking the one just above it, right? >> Oh, I think I think I I understand what's the issue. It's we should be the left one. Right now we're checking this one. It should we should be checking that the left is the same stone, not the right is the same stone for our hard-coded one. >> So we should check. when we get into >> Yeah, but hold on. We will be checking the last one at some point, >> right? [\[20:01\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1201s) But right now, the one that causes it to be missing. >> Oh, because it's almost fully surrounded, >> right? So if if we go inside here and we go surround on left is true. Oh, surround on left is true. >> So that's that's bad. >> Wait, two three two. Am I doing am I understanding something wrong? [\[20:31\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1231s) Three and then two. So I think it's removing that because it thinks it's surrounded by on all sides. No. >> Wait, is it surround on right is false? >> Well, this is almost fully surrounded. This is not just the one we're looking at. Is the symptom is that this one will be empty at some point and then the other one won't work. [\[21:11\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1271s) I think I I think right now the problem is that it is thinking this is white. I mean we think we think it as looking at this one but actually looking at this one. So this is thinking this. >> Why do you think it's that one? >> Because it says surrounding color is black. So that means it has to be a white stone that we're looking at. Right? If I go back to the call stack. [\[21:50\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1310s) >> Well, what's the >> Well, what's the current color? >> That's what I'm trying to figure out. >> What's the color in XY? X and Y are three and two. Okay. Yeah. So if I [\[22:22\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1342s) >> you're in board just say get stone color I think. >> No it it it says that I don't have a reference. It must. So if I can do like opposite of it, it's black. So it should be white. The color we're looking at is white. >> That's assuming that this method is actually working. >> Yeah. >> If we say just get stone. If we say this. [\[22:54\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1374s) >> All right. We have stone color matrix, right? We have access to stone color matrix. Oh, this time. Okay. Yeah. So our current color at three and two is white. That makes sense. Is get stone color. Maybe we get the X and Y reversed as well. >> Maybe something's reversed. So the the filling the board, right? So maybe get maybe get stone color. [\[23:25\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1405s) You're right. is reversed. Okay, so we're always saying X and Y. We're always saying add stone X and Y stone color matrix and Y equals stone color. [\[23:56\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1436s) So, this is >> Yeah, sorry. >> You want to open it up? I want to open it up. I want to see what's going on in this bad boy. It's one, two, right? One, three. >> We should have two and one as well. White >> two, one, two, two, two, three, two, four, two, two, three. We won't know because they're exactly symmetrical. [\[24:28\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1468s) What if we just add another white to one of the rows so we'll know exactly which one it's supposed to be in the DSL. Like if we go here, >> we have I mean three 32 here is the same as 32 here. We have >> no way to know if it's reversed. >> Or we can just like offset it. like put this. >> Yeah, but what if we just did the This wouldn't be symmetrical if we just did that. [\[25:06\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1506s) >> I think you get outside the buggy. >> Yeah, >> no, I meant I meant like maybe it might be better if we just move everything to like a different number. So one so then the X and Y X side would be between four and seven. Y would be between one and three. Now all the tests are passing. >> Oh, this one is because this is this is incorrect. This should be 52 and this should be six [\[25:37\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1537s) Six. Oh, now it's passing. What the Hey, what the what the >> Oh god. Okay. >> All right. >> Okay. >> I don't I don't [trust](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134 "How to know you trust a test (The Art of Unit Testing, 3rd ed., ch. 7)") this test to be honest. >> well, I think we're just seeing a symptom that [\[26:09\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1569s) We might have a bug when we're really close to the edges. >> Yeah. I'm I'm going to run all tests. Okay. >> But obviously >> we found a bug. >> There is some sort of bug here. >> Would you agree? >> Yeah, I agree. >> Oh man, I choose. Okay. So, we have to recreate it. We can't just back away from it and assume everything's good, dude. We have to stand by our principles [\[26:42\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1602s) And do this thing like real men and women. >> Okay. Stones near edge. Okay. >> Okay. >> So now let's see delete. So, at what point does it be begin to be? >> You need you need to change this stuff too. Right here though, too. This would be [\[27:13\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1633s) Four and five. [\[27:50\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1670s) Cool. So, we do have So, here's our bug near the edge. >> Hello, bug. Nice to meet you again. Why do we think this is happening again? But, but at least we know that this only happens when we're near an edge. What if we move it to the bottom edge? I mean, one row down instead of one row left. >> All right, >> let's see what happens. [\[28:30\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1710s) And then we need to move this to three. >> Okay. >> Okay. What if we move it now to the right? I want to see if this is a problem with the left edge or the top edge or both of them. And the assert [\[29:06\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1746s) >> Okay. So now we know that it has to do with any of the edges. >> Okay. >> Do you agree? >> I agree. So, let's duplicate this test so that we have one on the left edge and one on the Actually, what it tells us is that if we're not on the top edge, something's wrong. Am I right? >> we can try. >> Hold on. Hold on. What I'm saying is that [\[29:36\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1776s) The problem here if we move it one line I mean you can just delete the line with number one like this >> I think the test would pass because when we do the assert like this [\[30:16\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1816s) >> Okay. So, what I'm trying to say is is that we have two conditions that cause this to fail. the color not near not near top edge [\[30:49\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1849s) And this is near edge near left edge. And this one should be Yeah, this is the near left edge. [\[31:21\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1881s) Two and three. So now we should have two failing tests. These are two different or maybe caused by the same bug. >> Mhm. >> Okay. >> Okay. Because we do have situations where when we have two when we do have a test for two opposite color stones that does pass. >> Would you agree? >> We do. >> Okay. >> I remember us having one >> two opposite color stones. >> Yeah. This is where the really helps. [\[31:52\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1912s) >> Not near top. Remove opposite this one, I guess. >> Oh, this one, right? So, >> this is when it's passing. >> Mhm. Okay. Do you notice how the naming really helps now? >> Okay. So, now we can choose to what if we can just simplify this? Is there a simp way to simplify the test even more? [\[32:25\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1945s) Which one do we choose to debug? We Well, we debugged the f we just debug Well, we didn't debug any of these because this one was moved up to the top. So, maybe this one we just debugged. >> You want to debug this one? >> Yeah. >> Okay. >> So, should we comment out this one? The top one or >> do you want you want to comment this one out? >> Sure. Actually, >> just leave it for now. Okay. >> Okay. What's the conditional statement adding [\[33:00\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=1980s) Four 43 right or 34? Okay. >> no, that's not the X. >> Ah, I had the wrong one. [\[33:32\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2012s) Oh, this is Oh, there you go. Okay. Should be three, four. All right. >> And then where are we? Wait, why didn't you step into check stone or round position? >> Oh, I forgot. My bad. Let's start with >> Oh, you know what? Let's see now the status of the current board. >> Oh, I I misunderstood. [\[34:04\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2044s) All right. >> Okay, never mind. So, let's debug again. >> Yeah. right. So, we want to check the one on top and then off the color is white. So, we're checking the [\[34:36\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2076s) The correct stone. Guessing we do fully surrounded should be false. Okay. Almost surrounded. surrounded on left. So this one's the the one where surrounded on left should be false. That's true. Wait, >> which one are we checking? [\[35:06\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2106s) We're checking three and three. >> Yeah, three >> is >> black. So it should say surrounding on left. So that's why I'm saying Oh, so it it returns true and it actually has a bug, right? >> Yeah. Well, it's saying that surrounded. They're saying that this one is is white. >> You can just press shift F9 on that. By the way, >> shift F9. [\[35:36\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2136s) >> Selection. Yeah. >> I see. Yeah. Saying it's white, but it's supposed to be black. Oh, my screen isn't too happy. So, X is three. So, two and three should be black according to our board, right? [\[36:06\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2166s) >> Mhm. >> Interesting. What's all this ghosting? Yeah, I don't know what's up with this ghosting. >> Okay, now it's better. >> so okay, so at least we we have something weird that's happening that we can zero in on. Right. >> Right. >> So why if we look at the positions on the board right now, what do they say? [\[36:41\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2201s) >> So maybe we should go down to call stack right now in the board.cs. CS check the position or the stone color. So two two three is white and 3 one. Oh >> is this >> X is two and Y is three. X is two. Y is three. [\[37:29\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2249s) >> Oh man. >> Okay. So I have a suggestion. Let's simplify this. Let's see. if the bug is in the DSL or not. Let's add >> it is it is in it's the way we writing it. I just realized that >> it's supposed to be it's supposed to be like it's supposed to be white white black white black white. But I thought we fixed this last time. I don't get I thought we because like this is X. This is Y. [\[38:00\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2280s) So this must be actually no. Never mind. I'm confusing myself again. >> Okay. So, so let's simplify. Let's replace the fillboard call here with actual calls to add stone just like we did before we had the DSL. Let's see if the problem is with the DSL or not. Okay. Let's get rid of that parameter. >> All right. >> What I would say is can you stop debugging? [\[38:30\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2310s) >> Yeah. Okay. So, what I'm saying is this one. Now, we're just going to add it on our own board. Add stone. We need white at two and two. Agreed. [\[39:00\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2340s) >> Yes. Yes. >> Three and two. >> Yes. >> And one and three. >> Yeah. [\[39:32\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2372s) >> Four and three. Yeah. Yeah. >> And so now let's add the black which is two and three. >> Mhm. Then we should have back to white. Three and four. [\[40:05\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2405s) And lastly, but not >> we wanted to do three three four last, right? Wait, why you doing? No, you >> now we need four. Four. >> Okay. >> Did I get it right? >> Three, four, four. Four. You mean two You mean two four and three four, right? >> No, these are the bottom ones, >> right? So, two four and then three. [\[40:42\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2442s) >> Oh, yeah. Two, four. So, I added the Okay. Two away. Now one is failing instead of two. >> Yeah. I Yeah. >> it's still our DSL that's a problem. Damn it. >> Did we Did we switch to axis? I thought we switched to axis. >> Yeah, we did switch. >> But obviously we didn't fix everything. [\[41:15\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2475s) >> Was our initial switching to axis wrong? >> Damn it. Actually, I if I remember correctly, switching axes didn't do anything because we were trying to figure out the problem. >> Yeah, we did fix it. I remember us fixing it. >> Do you want to try it again? >> I feel like we were so right. >> Oh, we didn't. It's supposed to be We didn't I remember we switched the J and the I. [\[41:46\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2506s) We didn't switch it. just >> Oh, that's >> your change didn't include include that, I guess. >> Damn it. >> So, what? I didn't commit the last change. >> No, I I I thought you included it. >> I did. >> What should I do now? >> Should I just go kill myself? What should I do? Just tell me. [\[42:18\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2538s) This is >> okay. This is so what why don't we go like this? >> It's totally mind mindb blowing right now. >> That's why kids you shouldn't have any logic in your tests. >> Okay, everything's passing now. Sweet. Okay. Can you please commit that? >> All right. I'll commit this right now. [\[43:00\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2580s) How is switch access for fillboard? field for some >> just amateurs. We're amateurs. The world knows that now. >> I I swear that I saw us fix it though. >> I I've I've seen many broken promises and swears software. >> We got to All right. Now we can continue. >> Jesus. [\[43:31\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2611s) Okay. So now can we can we go ahead and say it's wrong for us to have the a hard-coded check just on the right because that's what we did so far, right? We always check to the right of the current >> Yeah. position. >> So what we can do next is we can set up the board like this. Don't change existing tests, dude. [\[44:02\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2642s) >> All right. All right. I'll make a copy. All right. >> Control D. Right. >> Mhm. >> All right. how should we do this? Opposite color. Just name it number two. >> No, that's not the difference. else >> the simplest proof that we are doing the wrong thing. [\[44:38\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2678s) >> I'm just going to make things a little more readable. Maybe like this. Sure. Okay. Well, the simplest I was going to have it was like like that. And then board add stone at 24. [\[45:09\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2709s) >> don't forget to to name the the color. >> That's first one. All right. And then the should be same 2 three and three three. Oh, it turns green. >> Mhm. I don't think that's a problem. I think that we we just need to basically create a board [\[45:40\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2740s) Where we have black and black like this of course it's not going to work. Come on. I'm just trying to move the mouse. The the the character one. Thank you. >> Like this. We don't need that one anymore. [\[46:17\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2777s) >> Okay. >> See what I mean? >> Yeah. So this should we should be getting two empties on position two and three and >> two four >> two four. >> Cool. >> Okay. Because we just checked to the right. So surround opposite color stones [\[46:49\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2809s) Vertical. Okay. >> Okay. >> So just to make it maybe a bit clearer. >> What's the [simplest way](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") to to pro to make everything pass? So, I was wondering about how we were going to do that, especially when we had the is almost surrounded hardcoded with the right side. [\[47:21\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2841s) So, I'm I'm not really sure where you were going with the is is almost surrounded, almost fully surrounded. so I was going with the simplest solution >> and just ch saying, well, it's fully it's almost fully surrounded. >> and then just add a check to the to the bottom. >> That's what I was thinking. [\[47:52\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2872s) Just hang until you make it. So it would be on the bottom just like we checked on the right. So I think the the simplest solution then would just to like count to like [\[48:25\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2905s) Increment and check check till three and then this is basically what we're doing right we're only checking that it's three starting on three sides. >> Yes. >> So I think >> no but it's not just surrounded on two sides. It's surrounded on the fourth side with the same color. [\[49:07\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2947s) >> now of course. Oh, now we broke four. That's great. >> How about we go back? >> Yeah. I'm just >> how we go back one test like instead of doing vertical and I break yeah I try to write another test to break the other test. So I want to go I want to like comment this test out for a bit. >> Yeah but we have to undo my changes first. >> Okay sure you do that. [\[49:41\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=2981s) >> so like this. Okay, now we can go back to commenting the test. Why do you want to comment it out? What what are you trying to do? >> Because there's a very there's a incorrect assumption that's bothering me a lot. So I think if I take this test, control D. I just want to verify maybe maybe I could be wrong. Let's call this something else. Just say two for now. You can double click on the on the pane tab so we can see more of the code as you write it. [\[50:14\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=3014s) And then double click. >> I see. So if I if I just have it like this and I just check position status 3 23 by itself. So this supposed to be filled still. Yeah. >> So this so this supposed to be Phil. [\[50:44\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=3044s) >> But why don't you make it just one difference from the other test, not two. You made it two characters different. You can just remove one character and it will still fail. >> >> you remove two whites. Remove just one white. >> Okay. Which white do we want to keep? All right. Yeah. >> Why is it not? >> It's building. Oh, it's not building. [\[51:15\]](https://www.youtube.com/watch?v=fgfPhEW6934&t=3075s) >> Yeah, because position status should be filled, but it's not. It's F. >> Oh, how did that How did that happen? All right. Oh. ## Related - [Debugging Unit tests using the VS.net debugger](https://osherove.com/blog/2004/1/9/debugging-unit-tests-using-the-vsnet-debugger.html) · osherove.com How to step through unit tests in the Visual Studio debugger, as the pair do with conditional breakpoints. - [Why tests fail](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_135) · The Art of Unit Testing, 3rd ed., ch. 7 Book section on why tests fail, useful for telling a production bug from the DSL bug found here. - [Test Coverage and testing angles](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html) · osherove.com On using coverage to see untested code, like NCrunch markers showing the almost-surrounded branch never runs. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [How to know you trust a test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134), ch. 7 #### The Art of Unit Testing, 2nd ed. - [Building a test API for your application](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6), ch. 7 #### osherove.com - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) [Previous lesson A Refactoring Dillemma](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/a-refactoring-dillemma/) [Next lesson The Big Refactor](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/the-big-refactor/) --- title: "The Big Refactor" url: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/the-big-refactor.md" canonical: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/the-big-refactor/" tags: [] author: "Roy Osherove" description: "Lesson 10 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 1:28:13. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # The Big Refactor 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD Pairing Sessions - Building a Go Game](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/) 3. The Sessions Lesson 10 of 11 Duration: 1:28:13 [Watch on YouTube](https://www.youtube.com/watch?v=pAmJiH44S08) ## In this lesson In session eight the pair refactor before adding a group of three, guided by don't repeat yourself and the [single responsibility principle](https://osherove.com/blog/2013/3/6/refactoring-string-calculator-with-solid-principles-in-mind.html "Refactoring String Calculator with SOLID Principles in Mind - Examples Needed (osherove.com)"), since simple code forces thinking about tests. Removal logic moves into a stone remover class with a removal arguments parameter object, leaving the board to manage the stones. The checks become removable detector classes returning lists of position tuples, one looping over checkpoints, and the classes move to their own files and folder. ## Transcript 8,491 words [\[00:07\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=7s) Hello everyone and welcome to session number eight I think. Isn't it Raymond? >> I think so. >> And how are you dealing with all this? Getting bored? >> No, it's it's getting more exciting every single time. >> Well, that's that's very kind of you to say. So where did we leave leave off last time? >> So last time we added determine [\[00:43\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=43s) A group of two surrounding group of two in a vertical position. >> Oh yeah. >> So >> someone said >> we added that we're we're actually digging ourselves into a hole there. So that might be interesting to see how we end up with what kind of algorithm. >> Yeah. Yeah. well I was I was thinking that we might end up refactoring in the end. So >> well we can start refactoring now if you want or we can add some more features. [\[01:18\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=78s) Let's see what do we have so far. Are we do we like the code that we have? Let's see. Yeah, >> not crazy about it. Remove stone surrounded is kind of looking weird now, >> right? With the fully surrounded and almost surrounded parts. Yeah. So, we have a like a surrounded on top on to the right. [\[01:50\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=110s) That's interesting. >> so this stuff, this code is only for like two stones connected together like like what happens when we add a third stone. So should we that would definitely like change things a lot. So should we refactor before we start adding tests for a group of three or should we add add that and then that would be taken into consideration in refactoring? It's our choice. [\[02:21\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=141s) Usually I would say let's refactor first because the code is already kind of ugly >> also. We have two choices. I mean just about that feature. We can either choose to implement almost surrounded to the left or to the to the bottom. >> or go to surrounded by three or more. I mean three or more being surrounded. >> Mhm. So, and based on our choice, our design is going to change as well. [\[02:54\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=174s) >> All right. >> So, what do you think? What do you want to do first? >> I think normally if I was to do this on my own, I probably want to consider refactoring. At least in the position where our code is right now, I feel it's really hard to I feel it'll be a lot of work to add in another test for surrounding a group of three with the code we have right now. >> Sure. >> So, >> okay. So, how do you want to refactor this? [\[03:26\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=206s) Do you have any interesting ideas? So I I just find it interesting in the first place that we have and is fully surrounded by and almost fully surrounded by. >> Okay. >> >> and they're kind of themselves, >> right? >> Okay. So, >> so the thing is like you know how like I implemented this before, right? [\[03:57\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=237s) So the way I did it though, I'm worried that sometimes that the way I did it before might affect like the test that we write or like maybe just I might end up just jumping into it and skipping the whole [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") process because the so the way I implemented it was that I would get all the stones and then get all the and all the stones that connected and then get the positions that are adjacent to the stones and check that they're all filled with white. [\[04:39\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=279s) >> Okay. I I don't understand how is that happening in terms of design though. >> I mean like right now I I'm worried that it doesn't I mean it's totally different from what the way we're doing it right now. And I'm worried that it's not like driven by tests. >> Mhm. Okay. So >> So is that is that a problem? >> Well, I'm trying to understand is it a problem on on your own different implementation? [\[05:10\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=310s) Is that what you're asking? >> Yeah, like switching from one implementation here to another implementation. Well, it wouldn't be a big problem, but my guess is that the possible risk here is that there would be some features that aren't being tested that already exist there. So, there would be it would be more generic than this code >> and so we would have less of a inclination to write any tests for it, >> right? I see. >> Okay. >> Okay. I mean we could switch it all and then some these things will actually work but then we won't know which features actually exist. [\[05:46\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=346s) We will have to like guess which test we want to write. And in in real life usually if you do it like that you just say okay well it actually works really nice. I can't think of a failing test for this and that's it. >> And the whole point here is that you're not objective. We are not objective when we write the code. So >> by writing it as simply as possible, we're forcing ourselves to also think about the tests. >> Okay. >> So if we implement everything, we're not forcing ourselves to think about the test and we're basically saying, yeah, well tests are not as important for this. [\[06:23\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=383s) It doesn't have to be covered in in terms of functionality. It just has to have some tests, >> right? >> And I want every character, every line in the code to have a reason to live >> basically. >> Okay. Now in terms of possible refactorings there are two kinds of rules that I always look to and one is don't repeat yourself >> and the other is the [single responsibility principle](https://osherove.com/blog/2013/3/6/refactoring-string-calculator-with-solid-principles-in-mind.html "Refactoring String Calculator with SOLID Principles in Mind - Examples Needed (osherove.com)") >> right >> okay so that every method has one reason to change not two not three [\[06:57\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=417s) >> so in terms of refactoring I I I think there's plenty that we can do here >> right >> I mean if I look I look at the code. Remove stone is surrounded. I mean, this thing here, I mean, if you look at this, this is actually setting two stones. It's actually setting stones to empty, right? >> Right. >> So, and this the same here. [\[07:28\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=448s) >> Mhm. So what if just as a as a as a start measure I will refactor and say remove stone with XY. >> Okay. It's the same here. [\[08:02\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=482s) >> It's almost the same here, >> right? But x + one and here it's xy and xy minus one, >> right? [\[08:38\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=518s) Cool. Now when I do that, I see that I have removed stone. I don't have to repeat this three times, >> right? >> That makes sense. >> Uhhuh. >> I mean, it almost looks like I have to remove it if it's fully surrounded. >> Right. I see. >> So, you want to make one conditional statement for that? >> What? I I was just wondering how you're going to make it not repeated. >> Well, I don't have a magic formula. [\[09:11\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=551s) I'm just I'm just thinking out loud about how I might do that. >> Okay. >> Basically, I don't want to if I'm repeating myself here, maybe there's a way I don't have to do it. Mhm. >> Maybe there's a way. I always remove the current stone and I possibly also remove a stone next to it, >> right? [\[09:41\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=581s) What would you like say about if you move this this line out and then you put like these a copy of these? I it would be another duplication but it' be a duplication inside the conditional. >> So you would send them as delegates. >> I I don't follow you mean send it as delegates. >> So you would send them as as a boolean parameter or as or as action delegates to be invoked at the method. [\[10:18\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=618s) I meant I meant like copying this into >> like a remove stone if >> if or but that would be like duplicating the conditional. >> Oh, I thought you meant call remove stone with the conditional. >> What do you mean by call stone with the conditional? Remove stone. [\[10:48\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=648s) This >> Oh, I see. >> Like a remove stone if Let's see. So, let's think about this logic for a second. Okay. [\[11:19\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=679s) Remove stone surrounded. Rem we remove it. If it's fully surrounded, remove it. Oh, so that's interesting. So, so the way I think about it now is that we do have an interesting refactoring we can do here. So, remember when we had strategies that didn't make sense for detecting that something >> should be for detecting a winner. >> Mhm. >> Because there's only one way to detect a winner, I guess. But here >> we might have strategies to remove stones. [\[11:52\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=712s) >> I see. >> First one is remove a fully surrounded strategy. Second one is surrounded on right strategy and this one surrounded on top strategy like a removal like a chain removal strategy or something like that. And that way we don't have to have the if we would basically have like either a base class or something like that that basically does the checking and has like a strategy for detecting all the different things. [\[12:24\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=744s) Okay. >> Does that make sense? >> It makes sense. But the thing is that if this is a separate strategy and this is a se separate strategy, >> the almost surrounded is going to be calculated twice. Is that going to be fine? >> Well, we don't care about performance yet. >> Okay. >> Remember, we h it has to work and then we can optimize. So we want to reduce duplication in code first and then duplication in like performance-wise [\[13:00\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=780s) Is secondary for now. >> Yeah, later we can optimize the hell out of it. But it has to work. >> I mean it has to be maintainable and when when that works we should hopefully have only one place to change it. >> Maybe somewhere in the base class or something like that because you you won't have to have that duplication. you might have the like the checking almost surrounded in the base class or somewhere. >> Okay, >> so here's an example. We can start the refactoring by saying [\[13:30\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=810s) Stone remover equals new stone. Okay. >> Okay. X and Y and it takes in the rules and the board. Actually that that that already is too many parameters. So I would actually call it directly with a like with a parameter object like u new removal arguments [\[14:05\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=845s) That has these properties. So we would have like x = x y = y. The rules, right? Rules rules and board equals board. [\[14:36\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=876s) It's inside the board class. So this >> Yeah. >> so new removal of the thing. You have a extra >> is this right? >> Parentheses like right here. [\[15:08\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=908s) >> okay. Let me just finish that. Did I miss anything? >> I don't think so. I think I think you got it. Oh, you're missing a comma right here. >> Okay, put it. Cool. So if we had the stone remover class, first thing is we would put all this into that stone remover class. >> Okay. And then we would refactor to different strategies. [\[15:39\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=939s) >> Okay. >> Otherwise the board knows too much already. >> But we going to go ahead and say create a stone remover. [\[16:20\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=980s) Just basically go ahead and create all these properties. [\[16:56\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1016s) And bor. Yeah. >> Something is more accessible than the other. Let's see. Maybe rules class is not public. >> Sure. Cool. So now let's see where [\[17:33\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1053s) So now basically I would go and say remove horrible. >> What are you typing on? Probably something that's not a keyboard. It's like a Schwarzenegger was typing. >> Yeah. >> Then we would have all this [\[18:05\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1085s) And our first thing is to get rid of rid of all that logic. >> Can you refactor and put that all that there? I think that it'll be faster. So take all this >> Yeah. and put it in the remove method which doesn't exist yet. >> And put it in in stone remover. >> Yeah. In the remove method which we have to Yeah. to generate. >> But what be the best way to generate is like this. >> Yeah. Exactly. >> Tab tab. [\[18:42\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1122s) What the hell? Nope, that's not what we meant. Now we Okay, now now if you Okay, try to paste it. See what happens. Yeah, we also need to remove stone. Forgot about that. >> >> it's still in the board. >> Oh, it's still in the board. I see. So move this out. [\[19:26\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1166s) >> Yeah, just import it. >> Alt enter. >> Yeah, but the remove stone method is still on board. >> That's why it's saying that it doesn't There's a method called remove stone. It's just like >> you passed it. >> You're talking about this. >> Yeah. >> You're talking about this method to remove >> stone. We It's still on the board class. >> Yeah. [\[19:56\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1196s) So, you don't want it inside the board class. Do you want to take it out? >> Yeah. Because it's it's >> or we can make it public. >> We would say board. I see Nick. I don't think I don't think there's anything wrong with board. >> Except that we have a class that the whole point of it is to Oh, because it needs access to the stone matrix. Right. >> Right. [\[20:27\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1227s) >> Public. Cool. And so we just have to >> What was your issue with having a remove stone in the board that you had or has that has to access another class? >> Yeah, I mean it's a stone remover, but that's okay. I forgot that it needs access to the board matrix, >> right? You're mistyping everywhere. So this is saying you treating as a static I mean we had to create a property for board right now >> we should already have one oh oh it's args.board actually [\[21:04\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1264s) Right so we have to save it or we can if it's it can't be static right >> right >> yeah so we just have to have a property called board that we can or args.propy property called board, >> right? >> Introduce initialize args. >> Nice. >> And then we can say args board. >> Okay, I can type it for you. >> Okay. [\[21:51\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1311s) Okay. >> yeah, but remove takes an X and Y. No, >> I see. >> No, it doesn't. >> Yeah, I thought I thought it So, it didn't Oh, so no, the you define X and Y in the remover. Okay, so you're talking about args.xy, >> you know. But you know what we could do is just to make things much easier instead of replacing rxy everywhere >> right >> is we can do [\[22:25\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1345s) >> well what happened there's ghosting >> okay but what if we just did like this yeah I can definitely see the ghosting here That's a disgusting thing in viewer. >> Maybe it's better if I Oh, actually I do it right now. [\[22:57\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1377s) >> There we go. >> Okay, it's cool. >> What if we just did this? Then we'll just say remove args x. [\[23:33\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1413s) >> Okay. But what about the rules object? Do you want to define that as a parameter too? >> Well, we can use rx.ruules. It's easier. >> Okay. >> We can make this non-public if we really wanted to. >> okay, >> I've gone ahead and copied this for you so you can do your thing. >> All right. [\[24:16\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1456s) Okay, we're back to green. That's good. So, we're doing it slowly but surely. So, now at least the board and the remover are in different places. >> So, the removal logic, which is getting quite out out of hand, is at least we can at least it's it's clearer. So if we look at the board back here, stone added, check around and remove if needed. That's the rules, right? >> Right. >> That's interesting. [\[24:48\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1488s) The board has rules. The rules call check and the rules call them later to the board itself. remove stone if it and then the board calls stone remover. >> So we can make that nicer as well. We can go ahead and just maybe maybe the logic that goes through each one be different. I'm not sure. I mean there is kind of like a weird [\[25:19\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1519s) Path. See what I mean? >> Yeah. Can you go back to why why does the rules why does the board calls rules again? >> Well, we used to have a we have a method called check stone around position and remove >> which does this. So, this is the only reason because we wanted to have an algorithm just looks around >> the thing that was just added. [\[25:50\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1550s) >> Right. Right. Instead of instead of calling board the rules can actually create a new remover for each one and be done with it. >> That Yeah, >> that's what the board does anyway. >> Right. Well, wait. [\[26:20\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1580s) What does remove stone is do now? It's >> go to it and see >> where is it? >> I mean, we can just extract this method and put it and be done with it. >> You're right. You're right. Because it it doesn't do anything straight from the board. You're right. Go ahead and say [\[27:28\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1648s) Yay. Nice. Much cleaner. That's quite amazing how that worked out. So because we extracted it into another method. >> So >> pretty nice. >> We still have some work to do. But the point is that now the board has a single responsibility and that is simply to manage the stones. >> Right? >> Else it has the rules and the rules decide what to do when a stone is added. [\[28:01\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1681s) >> We has a remover. We I can has a remover that removes things. >> Mhm. So now we can make removal strategies here maybe >> right. >> So and again slowly but surely will work. So basically we can say like we can do all this right now as a method and say [\[28:32\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1712s) Remove My fully surrounded strategy. And then we would have this move by [\[29:03\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1743s) Right chain. >> we call it >> remove if almost surrounded except to the right. That's pretty long. We move to the right >> maybe. >> [\[29:35\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1775s) >> oh, it's turns and almost surrounded. That's interesting. Did I miss something? Did I >> I think you might It might have been when you selected the whole thing, you thought you were trying to return >> a parameter or something like that. So if you try control controlm or alt r and r enter is it alt enter. [\[30:05\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1805s) >> What are you trying to do? >> Control alt m to refactor. >> Oh alt. What the heck is going on? >> Control alt m >> or control alt m. Okay. I think it's because you it selected a return value right here. So you wanted void, right? [\[30:35\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1835s) >> No, the the the the problem is that we have an if here that uses something. >> Oh, it uses the same almost surrounded, right? Yeah. >> So if we did that instead, we would say So we're on top too, >> right? [\[31:06\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1866s) >> The strategy separate. >> Okay, I see. >> Wait. Let's call it removed if chain on right surrounded or if >> it's still going to return something. >> No, it says return void. >> Yeah, >> remove what? What would you you put in the name? >> All right. [\[32:03\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1923s) And I like how we're getting the feedback without running the test that we we didn't break anything. >> Yeah, it's very nice. Cool. And now we can go ahead and for each one create like a strategy for it and then later we can even remove the calls to the methods. [\[32:35\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1955s) Another po another thing we can do is just keep it this way. Okay. >> What do you think? >> I' I don't understand the other way though. I understand keeping this way. I don't understand creating a class and the one the other way you mentioned. >> Okay. So, it's almost as if we did the the get winner strategy. >> Mhm. >> But as a removal. So we would say fully surrounded strategy. [\[33:08\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=1988s) Okay. So we would have like a strategy. What if instead of strategy would have like a detector that tells you what to remove instead of removing it, right? Because we have a class that removes things. [\[33:38\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2018s) So it would be like removable detector or something. >> Sure. >> Removable. >> Let's go with that [\[34:12\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2052s) Fully surrounded detector equals new fully surrounded removable detector. Okay. Now the way it would work is that we would say fully surrounded room detector detect for the board would have like an args. [\[34:44\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2084s) Okay. >> Okay. And what it would return is like what we need is basically an array of XY positions to remove. >> Okay. All right. >> So how would you declare that >> and so pairs basically an array of pairs. >> well >> I don't know another way. >> Okay. >> Except this one. [\[35:14\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2114s) No problem. Results. Okay. It doesn't make Oh, alt enter to add the list. And alt enter again. Cool. And then basically is this one supposed to be is this one supposed to be this this value? >> Yeah. Okay. And then we would basically [\[35:48\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2148s) Do like a results each. This be the same line as this thing. >> Yes. >> Or do stone as to pull [\[36:20\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2180s) >> item one and tuple item two. That's that's what we're going to get. >> Yeah. But that's basically what I'm thinking. >> Okay. >> And that basically each one of those detectors might return multiple things. >> Mhm. don't care. >> So, is that thinking too far ahead? >> Well, we're already trying to make it a bit more general in that [\[36:53\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2213s) Is it too far ahead? Do you think it just should return a tuple and that's it? >> Sure, we can make it just a tuple >> just for now. And >> Sure. Sure. I like I like the way you think. We don't have to do it. We don't have to do it. >> I'm just saying like I'm just wondering [\[37:30\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2250s) Need to do a check if >> the null. Sorry. >> Would you need to do a check if the tuple is null? Like if the >> No, now you're Now you're thinking ahead. >> Now I'm thinking too far ahead. All right. >> Okay. So, basically, we're going to have this in the removal detector. Can you Can you make that? [\[38:01\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2281s) >> Yes. Oh >> yeah, sure. No problem. We can move it later. >> Okay. >> Actually, yeah, we have to call it a fully surrounded removable detector. >> Well, that >> that inherits from a removable detector, >> right? So, just I'll enter this one, right? >> Sure. [\[38:33\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2313s) And then we have a detect which is like an abstract method. >> it's abstract. This method has to be abstract. >> Okay. Do I need >> it has to be public too? public abstract. [\[39:16\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2356s) >> Is that is that not right? >> And I think it has to be an abstract class as well. >> Sorry. Okay. >> And now this class has to Oh, it's not override. Just Well, you're working too hard. You see that red line there? Just press alt enter. >> Alt enter. >> Yep. It's always alt enter. >> All right. [\[40:05\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2405s) It's basically the same logic in a different place, >> right? >> Except instead of removing it should be >> just returning just return the tuple of x and y, right? Oops. Yeah. If [\[40:41\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2441s) Oh, >> it's rx.x. Where the hell did the opposite color come from? [\[41:11\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2471s) Should we put in the opposite color inside here? >> Sorry. >> We add opposite opposite color to detect as a parameter. Interesting question. Where is the opposite color coming from? >> It's coming from before we had it right here and it was from remove fully surrounded strategy and it's that is from right here in the remove. >> I think it's just board.get opposite color or is it rules? You can just get it from rules. [\[41:42\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2502s) >> Okay. Okay. >> >> Just want to do it in equals. [\[42:38\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2558s) Mobile. >> Everything's broken. >> So, I'm guessing Hold on. Let's make sure. >> Okay. So, now we know at least that it's all in the new code. [\[43:09\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2589s) Well, I think if we look at the error code, it's going to say >> actually you'll see this code never gets executed. >> It's right. >> No reference, right? So, if I add in a line right here. >> Oh, yeah. We have just have to check. Yep. >> Oops. >> Yeah, if you added a line right. Well, I was that if to [\[43:41\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2621s) Not know. >> Yeah, I think you can do if you hold on. Well, yeah, that fixes it. But I'm just saying I think you can do like this. If you go on tuple, you should be able to say check if it's not multi. >> Very cool. >> Okay. >> Okay. Now we can remove this. [\[44:23\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2663s) >> Okay. So now we have a class that knows how to detect like a single stone. Okay. >> Okay. Okay. So, basically the process would be to go ahead and create and each one of them will be strategy. The one that looks to the right, the one that looks to the left. >> Mhm. >> Now, what's cool about this is that then we can later do one that looks multiple places and it won't hurt all the others because they'll just return a list that doesn't contain X and Y if we already remove them, >> right? [\[44:56\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2696s) Right. >> Actually, that might be a problem because if we already removed something that's fully contained. >> Well, right now we're only using Well, actually, the code doesn't prevent it from using multiple strategies right now. >> Yeah. But we we I think when we get to three, we're going to get there and then we'll say the first one that that works is the one we're going to use. >> Mhm. [\[45:27\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2727s) Okay. >> Otherwise, they might collide with each other at some point. >> Mhm. >> Okay. So, you want to do the other ones as well, or do you think that the strategy of one to each position is one strategy? >> Strategy one to each position. >> I mean, one to the right, one to the top. >> Oh, that's a good point. I think that is one strategy that the I Well, is that generalizing it too much? [\[45:59\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2759s) No, I don't think it's generalizing too much. >> Well, we can try it. We can always refactor it later. >> Okay, let's try it. Let's You mean like try putting it as one strategy, right? >> Oh, by the way, have you noticed we don't need these arguments anymore? >> Right. Look at this. We can say that. We don't have to We'll say [\[46:55\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2815s) Okay, sorry. So now you what what I'm thinking is that let's see is that all these three are just a single strategy but it's possible that each one of them is a different one. So it's a single strategy that that's only partially working. I mean, yeah, not all three. I'm sorry. Just the bottom two, >> right? All right. Okay. [\[47:28\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2848s) >> But each one of them can be its own strategy as well. So, whatever you think makes sense. >> I I would I would like to do the single strategy or or a different version of a single strategy. >> Okay. You want to try and do it? >> All right. So, [\[47:59\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2879s) So the first thing I would need to do is change one of these to look like this, right? chain. >> Sure. [\[48:30\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2910s) >> With neighbor. No, chain. >> Well, by chain makes sense to me. >> Okay. By chain. Stranded strategy. Oh, detect your surround. >> Sounds like your left is out of batteries. >> How's that possible? [\[49:15\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2955s) >> >> Solves. >> Well, remember this one does not return a single one. It returns a list. >> All right. Okay. Well, right now the way we have it. Oh, yeah. You're right. It returns two. [\[49:46\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=2986s) You're right. You're right. I see. I see where you're going. I see where you're going with that. Okay. You're clever. So, because of that, I have to How would I do that change then? just just do the change as if everything's great and then make it compile because like well I guess it would make another detect [\[50:21\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3021s) Because then right now this detect is only returning a two but well like one is not returning a list. >> Yeah. >> Okay. But I think it will just force us to make the abstract return a list. But it will the previous one will just have one in the list and that's it. >> Results dot I like your for each use of list link. >> Now you can do control shift enter control shift space. Sorry. >> Okay. [\[50:51\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3051s) Is it this one? I see. Okay. And then what are you doing? [\[51:27\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3087s) Okay. So, what does this say? Change results. Replace change type of results. >> No, no, no. You have to change it to the abstract method level. >> I was I was wondering if it had if ReSharper was able to do that for me. >> Maybe Maybe it did. Maybe I missed it. >> No, it didn't look like it it did. [\[51:58\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3118s) So, this one. This one >> just used Hold on. Instead, what you could have done is just tuple equals detect dot first. >> Ah, >> wait. There's probably a link missing. [\[52:31\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3151s) If you go to >> Yeah. System.Linq. I think it's a parenthesis. There you go. >> Okay. >> So, let's make the other one work. >> New list. Right. >> Right. [\[53:21\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3201s) >> Okay, cool. Oh, something's stilling to build. Oh, it's because I don't have this one yet. That might be important. >> Say again. >> Yeah, that one might be important. [\[53:51\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3231s) >> so basically this copy this. >> Yep. What just happened? >> Tab. Tab happened. [\[54:25\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3265s) You want to do the X and Y like you did before? I I did this part enterable [\[54:58\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3298s) And then >> still not compiling. >> Well, it's this part because I didn't I didn't return the return the list yet. Oh, >> so Well, you know you have exactly two right now, right? >> Right. >> Then you don't have to like declare you just create a new list with the two in there. >> Right. If >> So you're talking about return it right here. [\[55:31\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3331s) >> Right. >> Mhm. >> Okay. Oh, how come it's like that? Okay. Is that right? >> No. No. It's a new list with an array. Remember, it's an array of neutrals. Hold on. >> Oh, okay. I I know what you're talking about. >> Okay. Do it. Wait. You're talking about this, right? [\[56:02\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3362s) >> No. Yes. Yes. Yes. >> Yep. >> Okay. >> And then >> just return null. >> That didn't work. I guess you have to return. >> I think it's the it's the checking if it's null first. This one is no exception value cannot be null. [\[56:35\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3395s) So this one still checking it's null. >> >> oh yeah true >> because he's calling first. >> Ah yeah I agree. >> So we can't return null in the in the strategy. We just have to declare it nicely. Just return an empty list. Ah, okay. >> Right. >> Oops. Sorry. You want me to do it? [\[57:06\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3426s) >> No, you do it. I think it will be faster. >> Okay. Like that. All right. >> Yep. >> And then this one, too. Ah, what? Something's still not wrong. Still, what's this? What's wrong when running? Oh, okay. I guess can't work. >> Contains no elements. >> Oh crap. [\[57:42\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3462s) >> Yeah. So we have to do it the stupid way. Get the list. See if the list is empty. Blah blah blah. God damn it. Can C# just help me out? But the list does not have any items, sir. I don't know what to do. >> Is there like a first or default? >> Yeah, >> which is better. >> >> Oh, that's better. [\[58:14\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3494s) >> That works. Cool. >> Okay. And in that case can go ahead and just do we want to copy these two lines to here now. Now that's working. >> I don't understand what do these where do they come from? >> From the remove chain on right. [\[58:51\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3531s) We have remove chain right >> because right now it's returning we're doing the first or default. >> Sure. It doesn't work. It's not the same. >> I mean if I >> but you know what we can do is we can just have like a method that goes through a list of tuples and that's it, right? like here. >> Isn't that what what it did? [\[59:23\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3563s) >> No, what I'm saying is that this would be like a remove all items. >> Okay. I think you deleted the one the line that you just entered. [\[59:53\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3593s) >> H >> you just deleted the line that you entered. >> That's stupid. All right. So I just moved that. Now, how to make it more generic? >> What do you mean more generic? >> Well, we were trying to combine this one with this one, right? To use one detector. >> Well, [\[1:00:24\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3624s) We don't have to have the second method call. That's the point. If we remove the second method call, then the first one should just work if we add that functionality to the to the thing. Do you I I don't think I understand why second method call. >> So >> we have this one right agree. >> So now if we didn't call this one at all but we just took the logic here and put it in the same strategy [\[1:00:56\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3656s) And make it return more results or different results. >> I see. >> Then it will work and then we can refactor the current strategy to make it more generic. Okay. >> So we remove something then we check and then we and then so it's small steps. >> I see. So what so what should I do right? So we should move that into the chain removal detector. >> Well first of all I would remove the call to the method you're in right now. So it would force me to put the logic that it has inside [\[1:01:29\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3689s) The strategy of the chain. I would just you know right on the method right here I would say let's not do that anymore. >> Okay. >> Right. So this method becomes ray I say okay >> if I didn't call it anymore and I wanted it to be in the strategy in the removal I would just go here and find a nice place to add that logic. >> I see. >> And when they both work together >> I would refactor again to make it more generic. [\[1:02:01\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3721s) Okay. >> So, I already copied it. Where do you want to add this? >> it would be the same right here. So, the difference would be >> Okay, that's good. >> This would be This one would be back to one. >> Mhm. [\[1:02:32\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3752s) Okay, that's good. So now everything's passing again. >> So we can remove the call to the other method, right? We just put it in a comment where we can remove that method al together. >> Right. >> So get rid of this. Ctrl L and then get rid of this. >> Yeah. [\[1:03:06\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3786s) Now, now we can go to the strategy and refactor it again, >> right? >> So now it's possible that the strategy has multiple ifs because it is a strategy that looks for different places. But we can make those ifs a bit more generic. Like for example, >> given an X and a Y. Okay. Like if we had a list of tuple pulp, sorry. >> Mhm. [\[1:03:38\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3818s) >> Of in >> Yeah, of course. >> I'll fix it for you. Sorry. >> Do not dare. >> All right. >> to check equals get checkpoints for X and Y. Now the checkpoints right now we only have two [\[1:04:09\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3849s) >> correct. Oh, >> collaboration through committee. >> So instead of surrounded on right here, we're checking the x + one, right? >> Mhm. >> And here we're checking the y minus one. >> Agreed. So imagine that we had a loop that that takes like a list of checkpoints. [\[1:04:43\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3883s) Given x we would get x + one y minus one like a tuple of of this a tuple of this >> and and right now it would just be these two tuples so that the we don't add new behavior >> right >> but then it will just work as a simple loop for each one of those so surrounded and surrounded on that tool see what I mean >> okay right >> do you see what I'm getting at >> I I see what you're getting at it it definitely looked It looks a lot cleaner now. [\[1:05:14\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3914s) >> Okay. So if you do so you want to try and get say say say say say say say say say say say say say say say say say say say say say say implement get checkpoints for x and y >> just return the hard-coded values or something. No, no, array. Forgot the notation there. >> Yeah, sorry to do that. [\[1:05:44\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3944s) But >> x. >> So we have x + one and y x and yus one. >> yus. Oops. And just to make it a bit more clean, [\[1:06:21\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=3981s) Sorry, that's what I meant. Now we have the list. Now, let's turn this into a loop. I mean, basically, we have the the the opposite color, right? So basically what we're trying to do is to turn this into something [\[1:06:55\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4015s) Of a loop right here, right? for each >> like to check dot for each. >> You want to try and and do that >> right? >> control shift space >> control. >> No. >> So for each tuple we're doing basically the same check, right? Actually here's something that will be I think this will be more readable. [\[1:07:28\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4048s) We make it a delegate. >> Okay. >> So it looks more like a method. Just >> sorry. >> Okay. >> You do it. I'm not going to touch anything. That's what you said. with the Okay, that's fine. [\[1:08:10\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4090s) So, we don't have to check on right. We just have to use the tuple xy. Remember >> tuple xy >> here in the x + one >> okay. Right. >> And the Aha. I see what I I see what the problem is. >> No, actually, no. X plus one is good and Y is good. No, no problem there. We're always checking XY [\[1:08:41\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4121s) >> and X + one and Y, etc. We're always checking the current one and the one next to it. Right. Right. >> Okay. >> >> so we have to replace the x+ one with what we got from the tuple. Right? The tuple already contains x+1. >> So it returns a tuple.x too, right? >> Exactly. [\[1:09:25\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4165s) This thing return type is void. It's supposed to add it to list in the return. So sorry. [\[1:10:43\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4243s) Holy crap. Look at that. >> Passing already. >> Yes. You likey? >> I like I like. >> Yeah. Much better. >> Now we can easily check for the other items and just add a very simple algorithm here. Just return a new tuple to check. >> Right. Well, like we we did we did check the other ones like if you remember we did it this way and fortunately >> Oh, I forgot about that. [\[1:11:16\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4276s) Cool. >> Yeah. Unfortunately, the reason why it works is because we're checking diagonally. If you remember where right here we checking diagonally and that that worked for it. >> Sure. >> That made everything work. >> So >> let's remove all the comments from there and commit. >> Okay. Let me [\[1:11:47\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4307s) >> you want to outline? Oh, okay. >> So that It might be better to say, oh yeah, but you want to delegate and you return the new results. I mean, it might be better to actually even refract that to a method instead. I'm not sure. >> right now I I think it's pretty clear right here. So, >> okay. But I will rename this to >> right right here. [\[1:12:19\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4339s) Ah >> actually no one to check to to like check for each and we have a tuple. So the tuple is item next to current. >> Ah >> what position next to current? >> Yeah. You know what it should be like? [\[1:12:49\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4369s) Nobody knows what item one is. We can say >> you want to make >> so you want to make an object for it or something >> like in x next I see >> to me the same with y y next to me or something like that I'm not sure [\[1:13:20\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4400s) >> and that say we would say, look at that. It's almost surrounded to the right. It's actually not surrounded to the right anymore. It's almost surrounded to some position. Right. >> Right. >> Something like that. I'm not sure. >> Args rules is surrounded X next to me and Y next to me. Cool. >> Mhm. We so the interesting thing is [\[1:13:54\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4434s) We probably move is almost fully surrounded into this strategy right and the same thing with the fully surrounded by because if I look at this where's all the find usages >> just control Victory these are the usages is >> I thought you meant to go to the code >> oh [\[1:14:26\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4466s) I meant the usage like it's only used inside >> here >> ahu >> so like >> sure >> if I control B and then I move >> look at that >> it's actually Scary. >> Yeah. >> I guess that's our next thing. [\[1:14:56\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4496s) >> Where Where did Where did I go? >> You put it on the base class. Maybe. >> Oh, you put in a base class. >> Maybe. >> Actually, that's the only class that's using. It's a don't. >> Yeah. That's that's what I was thinking. Edge. Why can't I resolve edge? >> It's part of board, I guess. [\[1:15:30\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4530s) >> it's part of board, right? >> So, >> so >> I think so. Well, if you go to the original implementation, you can see where edge is coming from. >> Where was Oh, it's part of the rules. We made it part of rules. Okay. >> So, rules.edge. [\[1:16:01\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4561s) >> So, well, it's going to be args.ruules. Right. Args. >> And I think it's a con, so it shouldn't be a problem. Try rules. edge and see what happens. Ah, okay. It's a >> because it's const. >> I see. Okay. >> Oh dear. Actually, you know what? Hold on, hold on, hold on. Instead of doing all that work, >> just declare edge and use it and just before that line. [\[1:16:34\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4594s) >> Oh, okay. Like an int edge equals the rules edge or something, >> right? Very nice. >> And now we have the board get stone color and that needs to change as well. >> Yeah. >> So we have args.board. >> Well, we can always do the same thing here. Board.board equals args [\[1:17:11\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4631s) Do we have have access to args? >> Oh, >> yeah. It's on it's in the base class. >> You put it as a field. You should have it. >> Okay. >> It's underscore. >> Well, it's like detect you pass the value args. So, it's not a property inside the class. >> Okay. So, you can move it to this method as an args. I can put it in the class. >> could show me also like how would I do it? [\[1:17:42\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4662s) Control al control. >> What do you want to do? >> You said you want to move it as a property of the class, right? >> control shift r in produce field. >> Okay. >> And now it's setting the field. And that's it. Okay. Okay. So that's so this would be args dot [\[1:18:13\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4693s) Board. >> Oh just as the first one. Yeah. >> Yeah. And then what's not what's not running? Oh, cuz so then this one would be delete and delete. >> Nice. >> Same thing can be done with the fully surrounded one too. [\[1:19:05\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4745s) So since Oh yeah, since we did we could have done this inside. >> How is take small steps? Small steps. >> Okay, >> don't change too many things at once. Make sure that you Crl P. Is there control P or Crl F? >> What are you trying to do? >> Move. Do the same thing with this. >> Yeah, this field >> or in line >> field. >> control shift R will give you the you want. >> Okay. [\[1:19:47\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4787s) Just copy. Wouldn't that all this make the the current class build a bit too big? >> The current class. >> Yeah. >> You mean this class? >> >> never mind. Fully surrounded. I mean, now this class and the partially surrounded class. Oh, actually what you're saying is that look, this one only needs the fully surrounded. The other only needs the partially surrounded by. Right. >> Right. Right. So I felt like that was with a single responsibility. [\[1:20:18\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4818s) >> It goes well. >> I like it. Nice. >> what's interesting is that well first let's commit so that we don't lose this stuff. >> All right. All right. it had a status. >> I thought I I can git ignore for that. >> Do you want to move the classes to different classes >> now? [\[1:20:48\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4848s) >> Right now, >> I want to keep this all in the same file. >> I think I think it's got big enough where we could move it to a different >> Okay. >> Yeah. >> So, let's do that. >> Do that first. Sure. >> Okay. Is there easy way to >> just F6? >> Just put F6 on the class name. >> Oh, F6 on a class name. [\[1:21:24\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4884s) And then you wanted to probably move this to another folder, right? >> No, no, no. Don't don't worry about it for now. Let's just F6 for the others as well. Six. >> Yep. Okay. >> Oh, strong. >> It looks like a class. I agree. >> Yeah. >> Okay. >> What about the removable detector? [\[1:21:56\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4916s) Okay. Another one. Pretty sure we're not done yet. I think. >> Go back to board. Let's see. Is that all we have now? >> We got a stone. >> We have a stone remover. >> Okay, do that as well. Cool. Nice. And the removal args. >> Removal args as well. >> Okay. [\[1:22:31\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4951s) >> Okay. Okay, now let's look at board. >> So you got the class board and we have the rules. Do we want one rules? >> Yeah. >> Okay. So board should only have boards now. >> Nice. Okay. And we didn't break anything, right? >> Yep. >> You want to run the test just to make sure? [\[1:23:06\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=4986s) Yes. >> so here's what I'm going to do now. Oh, correct. That's not what I meant. Well, we'll talk about that later. What I wanted is to now we can look at this. We have the we have the strategies, we have the board. So we can create like a folder or a new solution folder. >> it's under add. >> Oh actually it's project. [\[1:23:42\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=5022s) >> Yeah. Add. Pausing for a second. Okay. So, what I'm going to do is I'm going to move like a new folder. Let's rename it to like removable removals or something. >> Remove removal detector. Or do you want to just >> Yeah, we can go removal detectors as well. [\[1:24:14\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=5054s) I mean, I was assuming that you're making a folder for the removal strategies. >> True. >> So, chain removal surrounded detector args stone remover. [\[1:24:48\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=5088s) What do you think? >> I think removal is doesn't have a e after it. >> Oh, yeah. Sorry. >> And then everything else looks good. Yeah. >> Okay. Commit the thing. [\[1:25:28\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=5128s) >> what should I call it? >> The big refactoring of 2012. >> What we say? >> The big refactor of 2012. Sure. >> Actually, we should call it basically removal strategies or something like that. Refactoring to removal strategies. [\[1:26:01\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=5161s) >> Cool. >> Yeah. >> Just git push I think actually will work as well. >> Cool. [\[1:26:33\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=5193s) >> okay. So, do you, do you want to add another test for another feature or do you want to finish for today? >> I think we should finish your finish for today. It's already 3 3:00 a.m. for me and I got work tomorrow. >> It's only 3:00 a.m., dude. It's very early. Still have time. I'm just kidding. >> actually, I would remove all those gray things over there at the top, >> like this one. >> I would Oh, yeah. >> I would just continue cleaning. I mean actually my my next things to do might be doing the [\[1:27:06\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=5226s) >> what do we do? >> Say say again >> what I what I said is that my next new things would be to to basically look at that fully surrounded and partially surrounded and see how we can make that nicer. >> Okay. >> But we'll do that maybe next time. Yeah. Are you happy? >> I think we still have a bit of refactoring to do. >> Sorry. >> Still. >> cool. >> Are you happy with how the code is turning out now or do you >> Yeah, I I find it interesting like before I was a little skeptical about it, but after refactoring it's like a lot cleaner, a lot more confident about it. [\[1:27:44\]](https://www.youtube.com/watch?v=pAmJiH44S08&t=5264s) So, >> cool. >> Yeah. >> Okay. So, I'll see you maybe tomorrow. We'll see what happens. See you everyone. Thanks for hanging out with us. And cheers. >> Cheers. >> Bam. Okay, cool. That was nice. I now I'm feeling a bit productive. ## Related - [Video - Refactoring and Design Skills for Test Driven Development](https://osherove.com/blog/2013/10/14/video-refactoring-and-design-skills-for-test-driven-developm.html) · osherove.com Roy's talk on refactoring and design skills for TDD, the skills used to split removal logic into classes. - [Refactoring String Calculator with SOLID Principles in Mind - Examples Needed](https://osherove.com/blog/2013/3/6/refactoring-string-calculator-with-solid-principles-in-mind.html) · osherove.com Asks how far to refactor a small TDD codebase with SOLID principles, like the SRP-driven split here. - [Refactoring the production code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2) · The Art of Unit Testing, 3rd ed., ch. 2 Book section on refactoring the production code under passing tests before adding the next feature. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 [Previous lesson Debugging Excursions](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/debugging-excursions/) [Next lesson New Features](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/new-features/) --- title: "New Features" url: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/new-features.md" canonical: "https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/new-features/" tags: [] author: "Roy Osherove" description: "Lesson 11 of 11 in TDD Pairing Sessions - Building a Go Game (The Sessions), 40:06. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # New Features 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD Pairing Sessions - Building a Go Game](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/) 3. The Sessions Lesson 11 of 11 Duration: 40:06 [Watch on YouTube](https://www.youtube.com/watch?v=8gP8lAMjzQg) ## In this lesson The pair test that two stones which are not fully surrounded are not removed, and make the almost surrounded check count three edges of the other color and one of the same. The fix also checks a diagonal, which they call the board-scanning algorithm rather than a game rule, like dispersing the fog in DND games. They add test cases, then a check above the stone for vertical pairs, fixing out of bounds errors at the top edge by returning empty there. ## Transcript 4,413 words [\[00:07\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=7s) >> Hey, so where you want to continue from? >> exactly where we left off. >> All right, so so yeah, right now I was renaming this test, not surrounded. >> Okay, so we were we were just saying even when it's not supposed to feel surrounded, it does feel surrounded. Right. >> Right. So, we're removing the >> Yeah, just like my emotional state sometimes. >> All right. Two is not surrounded. All right. I should not [\[00:48\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=48s) Not remove. So, this one you could probably check both of them still like what we did last time. >> Yep. Just double control D. >> Okay. So I can just control D. >> You don't have to. You can just not have any selection. It will just do the whole line. >> Oh, okay. Oh, that's cool. And 33. All right. Cool. So, [\[01:19\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=79s) Let's get rid of this assumption. Oh, God. Please. Let's do it. But you do it. I do it. All right. I definitely think it has to do something with this logic is almost fully surrounded. I'm sure >> the bug is that it thinks it is fully surrounded [\[01:49\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=109s) And then it changes the stone color. No, >> no. The book is it is fully surrounded, but we shouldn't be removing it just because it is almost fully surrounded, right? >> Mhm. So it maybe the best way would be to check out what is the stone that is not [\[02:23\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=143s) That is not the of the opposite color that is the same color. the stone. Maybe check what stone is that that is the same color and check if that stone is almost surrounded except for >> Oh, that's a good check. I like that. >> You know what I mean? So, like when we get this >> It's already doing that. >> No, it's not doing that right now. It just checks if this if it's there's four stones surrounding it [\[02:55\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=175s) >> and there's a black. Right. So what we need to do is that we if this is a black we also need to check this black is also have is full almost fully surrounded with one black actually that yeah that's one black that'll get passing it for now. So you need to check both of them is fully surrounded almost fully surrounded that would make it pass. >> Okay. >> So it would need to [\[03:33\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=213s) Have maybe out out X out Y for would that be like to make it too complicated. Is almost surrounded to the left, >> right? >> X + one minus one. Left should be minus one, right? >> I meant to the right. >> To the right. Yeah. [\[04:18\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=258s) >> to to the left. Try minus one. >> You think he's checking on the other direction? >> Yeah, just try minus one. >> Okay. >> Should I try it? It's almost as good. I think your change was better. >> So, the reason those are breaking, we Let's see the names of the tests that are failing right now. [\[04:50\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=290s) >> oh, this runs the debugger. >> crap. That's not what I wanted. Do you know what's the you want to make a shortcut for the running all tests? What I usually do is basically just have a shortcut to right click on the solution [\[05:21\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=321s) And then I just repeat that. >> I see. >> But yeah, you can have a shortcut to that. So which ones failed? Surround opposite color stones. Surround to opposite color stones. No, not near top edge. And surround opposite color stones remove. So we just broke all the existing edge cases because because in in all those edge in all those two color stones, this actually didn't work. [\[05:53\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=353s) So I I don't think we're far off from the solution. I mean not all these tests have us almost surrounded on right and on left. >> Do you understand what I mean? >> No, I think I'm a little lost with that. What I'm saying is that the only thing we broke >> is the three tests we currently have, >> right? [\[06:24\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=384s) >> For when we have two consecutive stones of the same color which are surrounded, >> right, >> which are fully surrounded. >> Oh, it's because we didn't because maybe this one keeps on checking to the right. So almost fully surrounded is returning false. >> Almost fully surrounded. It should return true if we actually check on the left as well. [\[06:55\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=415s) Right now we're only checking on the right. >> Yeah. So maybe we make a copy of that method. >> I don't think we need to make a copy. We just need to fix it. This is the the fix we wanted to do before, remember? >> Right. Okay. board get stone color of X and Y. Okay, at least I didn't break anything else. Oh, cuz that's the bottom. What I meant is [\[07:26\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=446s) The one on the left board or get stone color X Y almost. And yeah, I I guess we should just check fully surrounded by check by by by counting, >> right? >> Mhm. [\[07:56\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=476s) It might be easier. >> Sorry. >> No, but yeah. >> We're just going to go ahead and see what happens when I just start counting. intented edges zero. And if surround on left [\[08:28\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=508s) On top, right, surrounded edges plus+ basically agreed. So right now it's just it's it's checking if the color on the left and the right and the top is equal to [\[09:05\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=545s) >> You want to fix it? Now I want them all to be in the same line. >> I see. >> So I want it to be a single line for each one just so it's it's very simple just like this. Then we have >> surrounded on Right. [\[09:40\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=580s) Surrounded left equals. And then we would have basically surrounded edges is [\[10:24\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=624s) >> right now. I think you need to change this back to surrounded color. >> Why? >> Because you changed it. It's basically surrounded by its own color. You're trying to check it's surrounded by >> remember that it's it's ore. We are already checking. Oh, so we need to add an ore, a third ore to each one. So it's either surrounded by a different color or its own color. [\[10:55\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=655s) Agreed. >> Oh no. Then that then it will be four. Then the value will be four for the other one. I think this method is getting confusing now. >> Yeah, it does. But just to understand the logic here, something is considered almost surrounded when it's surrounded. For us, the simplest case is that it has three different color edges and one same color edge. [\[11:27\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=687s) >> Right. >> Okay. >> So, we need to have surrounded edges three and we also need to check u same color edge one. >> Right. I guess just copy and paste. It'll be messy. It will be a lot of code, but let's get it working. >> I just want to see if because it makes sense to me and it does. [\[12:01\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=721s) It is a lot of checking. We can make it nicer later. Right now, we have a bigger problem. Oh god, everything is moving so slowly on my machine here. So now we have surrounded edges. Same color. >> No, you're changing the wrong one. Of course, >> you want to change the one. Hold on. >> Same color. And here. [\[12:32\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=752s) Same color. >> Okay. I'll I'll do the changes if it's a little slow for you. >> Well, now I'm I'm in the flow, dude. >> All right. >> But now you can go ahead. Everything that requires scrolling is kind of a problem. >> All right. Oh, this one. Same color. [\[13:15\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=795s) What do we type before? Was it rules? >> No. board.get color >> board I get color stone color of XY exactly >> XY. >> Okay. >> And now we have to do the final check is we have three of one and one of the other. [\[13:51\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=831s) Okay, still failing. >> Yeah, I noticed that. Okay. So, that wasn't the [simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)"), I guess. But it definitely feels right to me. So, I'm trying to understand what have we missed and are we breaking different tests now? Just make want to make sure. So, it's still surrounding and surrounding. [\[14:24\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=864s) So, what I would go ahead and do is take one of the failing, debug it. Actually put a break point right here. Where would I put the break point? Actually, we need to check for X and Y on H1. [\[14:55\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=895s) >> So, we need to go to the add stone method. Right. >> All right. Notify stone added. So that's what we want for now. >> You want to set a conditional statement. >> >> so be four 44. >> Sure. [\[15:35\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=935s) Okay. Run it. >> Yeah. Debug it. fully surrounded. We expect. Okay. This one. >> This is 43. We're we're this is exactly what we want to check. Right. >> Right. >> Or three. Almost surrounded. Let's see what almost surrounded returns right now. [\[16:06\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=966s) >> Returns true. >> That's good for us, right? >> Right. So surrounded to the right returns false. So let's go back into that. >> Okay. So almost surrounded returns true or false. >> So almost surrounded returns true. Almost surround to the right returns false. >> Okay. So >> let's go to the first one. Just debug the first one. Well, the almost surrounded returns true. So, we want to do the to the right one, right? >> From what I saw, almost surrounded returns false and almost surrounded to the right returns true. [\[16:36\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=996s) >> No, it it returned it. No, almost surrounded to the right. I'm pretty sure I saw almost surrounded to the right. How do I back out of this then? >> just press F5. See what happens. >> All right. So, if I do F10, almost returns true. F10 again almost surrounded to right returns false. >> Okay, >> so we want to look at almost surrounded to the right. >> Well, actually that makes sense because almost all to the right is [\[17:07\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1027s) Actually 53. >> You're right. So you want >> almost rounded to the left. >> Okay. All right. So let's run. Let's get out of this. >> Yep. Let's >> just All right. This one white left. >> So it's still still something wrong. >> Let's go back. Go back. Go back. [\[17:38\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1058s) >> Oh, go back. >> okay. That's better. Okay. I guess we have to continue to debug because I'm want We will be checking the one to the left of it at some point. >> So, that's bore four, >> right? >> [\[18:17\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1097s) Okay. Now, we want to check is the the one at y - one. We don't have a y - one and a y - one and x - one. I think we should. >> Well, y - 1 is x -1 is a diagonal and we don't care about diagonals. >> We do care just for checking. No, I mean in this case wrapping the the black >> we would care about checking the one on the top left. [\[18:50\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1130s) We would care about checking three >> surrounded is only like top left bottom right. The diagonals don't make it surrounded. So I'm not sure what what she's trying to go with the diagonals part. >> We're not checking the the that the current stone is being surrounded. We're checking that the stones around the stone are being surrounded. >> Right. So this >> so we can check six stones, we can check eight. >> No, but like why would we want to check the stones in the diagonal are surrounded? [\[19:21\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1161s) Because the reason we check around the stone we were checking around where we added the stone is because it affects the stones only immediately around it like left, right, and top and bottom. It doesn't affect the stones in the diagonals. >> the reason I'm I'm thinking about it is because it's the best way for us is if we edit this, if I think if we just check this one, everything will be good. [\[19:52\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1192s) That's why I think it would work. >> Okay. >> We're not >> cuz I think our algorithm is specifically designed currently for checking just this one. >> All right. Sure. We could try that. Or we can just rewrite the test to make it pass. I think if we take this one out and add it last, it would make it pass. >> Sure. >> So like if I >> But I I don't think Well, I don't think the problem is with the test. [\[20:26\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1226s) That's the thing. I think >> I mean the test >> the test >> I mean we can try it right now but I think a lot of Oh I guess we can try it. It just seems a little bit weird to me. >> Oh it's definitely I think it feels weird. I agree. I'm just it's it's more of a what if this happened just like a like an Excel sheet. >> Just just control D, dude. >> Oh, it's too late. I already did it. [\[20:57\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1257s) All right. Okay. Everything less. >> Yeah. >> All right. Wait. Okay. Sure. >> Interesting. So, do you think if we add another test that that puts the the white on the left last we will have a breaking test? >> no. because the this [\[21:28\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1288s) That one will use this one to check it. So when once it gets to this one where checks the top it will actually check this and check that. So what what's happening right now is that these these two have to be almost surrounded. That's what our implementation is doing. So by by doing the oneway check diagonal we're checking if these two are surrounded. So for so if we take if we add this one last this will check these two are surrounded for the top part. So it'll pass. >> Okay. So my question to you is do you have a problem with the current implementation? [\[22:03\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1323s) Except >> I mean with with the with the line I just added, you just added >> besides that it's a little bit weird because it doesn't make it doesn't really apply to the the game like checking diagonally. But it works though. So >> well I I don't it it has nothing to do with the rules of the game. It just has to do with the algorithm that looks at the board. >> Yeah. >> Okay. So given something it it right now looks at up down left right and also diagonal left. [\[22:35\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1355s) That's it. That's all it does. >> Right. I just just imagine if I was to take this code and explain to someone how it works. It's a >> So maybe we we need to name this method differently. We can call it I mean look at the name of the method. Check stones around position and remove if needed. That's all that's what it does. >> Yeah. Yeah, I guess so. All right. We we'll continue and we'll see if >> the way I think about it is it's like do you know in all those DND games where you have the fog of battle >> and you look around it but you can only see part of the map as you walk around. [\[23:13\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1393s) >> Mhm. >> So this is like this is what we're doing. This method is like dispersing the fog. >> It's just a different algorithm for looking around. It has nothing to do with the game. >> Right. >> Right. stone. It It checks it based on the rules of the game, >> which I mean it could easily have gone through now all the squares in the game and check them. Who cares, >> right? >> Yeah. >> It's just >> so >> So obviously I obviously something is missing and all all the pet tests pass. [\[23:46\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1426s) First first of all we need to commit because this obviously doesn't happen a lot when everything passes. So, let's say >> All right. >> What features did we just add, by the way? >> the the one where >> where vertical vertical two two stones. >> No, we didn't. I commented that one. We added this one. [\[24:16\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1456s) >> Oh, so what? >> We added the one where >> Oh, where it's not fully >> assumption. remove the assumption where it's not fully surrounded then it doesn't remove the stones but I would also suggest that we do multiple versions of this test >> I agree >> so that we feel more confident but just commit for now so we have something [\[24:58\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1498s) Okay. >> Okay. So, let's do multiple versions of this test. Let's see what happens. >> What do you mean multiple version? You mean the vertical one? >> No. No. The one you just added where you said, "Oh, that's but it's hardcoded." >> Oh, this one. >> Yeah. Where you say, "Well, it's not really checked. It's just checked." it shouldn't be replaced if it's not fully surrounded. >> All right. So, forget control D again. >> Do you think the test case? [\[25:30\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1530s) No. Maybe. I'm not sure. >> Oh, you want to use the test case? Oh, so I see. I see what you meant. Okay, that's cool. Yeah, we can do the test case. Because you did something similar like that earlier. >> Yeah. But would it would it complicate things for you or not? >> No, I think it's perfect for this. Where did you add that though? >> But you should double click on the on the pane here so it's easier to add it. [\[26:01\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1561s) >> Double click. Didn't work. I had to drag it. Okay. >> Yeah. Double drag >> this thing here. This thing. It's pretty cool. Where where is you? Cool. >> I just replace the string with the other string >> first. Yeah. So, what did you call it? The other one [\[26:32\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1592s) >> called >> board map. I just wanted to make it consistent. Okay, >> but you have the wrong board map here. Yeah. [\[27:21\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1641s) Yeah. It's okay. Just remove that line. Cool. It's not pretty. It's not pretty at all. What is Oh, this ghosting. >> maybe you should copy it after uncommenting it and then comment out the other one. >> Okay. [\[27:53\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1673s) Whoa. Okay. Okay. Now you have the part in the test that doesn't compile. >> Cool. Now we but we do need to check different position statuses for each one. >> Oh, I was just going >> hold but but you need one more parameter. [\[28:25\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1705s) >> Oh, you just want to move the the missing things around. >> Yeah. >> Cool. Cool. Okay. Same positions though. >> Yeah. So, I was going to put the W back in here, but Oh, >> yeah. >> move this W. >> Nice. And then we can just check the other ones too. >> Nice. [\[29:19\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1759s) Cool. >> It took care of that. >> How many tests do we have so far? >> does it say doesn't say right now? 28. Okay. Commits. Well, >> first I want to make sure. >> Oh, so so add that as a test case, dude. [\[29:50\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1790s) >> okay. >> If you really care about it, >> I didn't really care too much. >> Set a tree with a test case. But if it makes you feel more confident, then do it. It's really important that you feel confident. >> We need some confidence after these few days, past few sessions, >> right? >> Okay. >> And just make sure >> commit. [\[30:29\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1829s) So increase confidence. >> >> no. >> Yeah, maybe. No. >> Added variations of [\[31:05\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1865s) God darn it. Okay, cool. All right. >> Okay. Let's see. >> Okay. So, you want to let's see what happens with this test now. This one fails. >> Okay, now it makes sense. >> So, let's make this pass and finish for today. >> Okay. [\[31:40\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1900s) >> Another option is to refactor some of the ugly code we wrote before. I'm trying to understand why why is it failing first still because we basically we do the checking around it if oh we >> we don't check on the top >> right >> partially surrounded I think so basically [\[32:10\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1930s) The easiest implementation would be basically copying what we did before. >> But hold on. What do you think is missing? >> Well, what you just said, we were not ch we're not checking on top. We're just checking almost surrounded to the right. This one would be checking almost surrounded on the top. >> Okay. [\[32:47\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=1967s) I think you just duplicate the if and change the if. Yeah. Yeah, I agree. Yeah. Yeah. We need an almost round on top. I agree. All right, let's see if this breaks it. Minus one. Oh, 15. [\[33:28\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=2008s) It's It's kind of like the same thing we did with the the left thing. So >> now six are broken. >> Oh, what? Oh, it's because >> the original one was this. >> No, what I'm saying is keep let's see which tests fail just to see what happens. >> Okay. >> Oh, by the way Oh, yeah. Hold on. >> >> Oh, >> no, no, no, no, no. What what I'm saying is you didn't make it on top. [\[34:00\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=2040s) Really? Just you didn't fix this. >> Oh, no. That one was 15. >> I'm saying is is that we're changing the wrong positions. We should say here >> >> minus one. >> I see. Oh, you missed it. I'll fix it. >> 14 now. But now would be a good time to to alt R and see just the names of the failing ones. [\[34:31\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=2071s) >> Well, the if actually I saw this one looks pretty nice this way. >> Okay, >> let's >> so let's just look at the names and see what kind of features you break. So we we broke add stone. We broke determine winner. >> This one is just surrounding a stone and removing it. >> Which one? >> This is the first one. >> Add stone to empty position is broken. >> Oh, this one's an index was outside the bounds of the array. [\[35:04\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=2104s) >> Look, look at this. Look at this. The second test right here. Add stone to empty position. Other empty position is unaffected. What is the What's the It looks like these are all outside the bounds of array errors. >> Oh, let's see. Index out of bounds. Okay, that's good. That's not so bad. They're all out. >> So, we just need to check if there isn't a Y minus one because all our tests are really at the top. >> So, that makes sense. [\[35:34\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=2134s) So, what if we shift escape this one? It's because when we when we did this, let's control VP. Remember how we added >> the edge? We have an edge. >> We have an edge. So maybe there's something wrong with that edge. >> Let's just check if y is bigger than board size minus edge. >> I mean if it's not bigger than that's that's all the check we need actually. I mean if we go here and say also surrounded [\[36:06\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=2166s) And y is bigger than edge it like this. I think you need to do that a little bit higher because the the the break the error is probably from right from the method when it calls is almost fully surrounded. >> Is it? >> I think it was >> I I think actually we're doing it right here. [\[36:37\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=2197s) I think if >> we don't need to check for Let's see. Okay. Y is bigger than two actually. >> And just add this here. Oh, you think it's almost surround checking? >> Yeah. Can we take a look at the error message again? >> Yeah, I see what you mean. I mean, yeah, we can we can do the whole thing here basically. >> Well, let me let me check the error message first. [\[37:07\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=2227s) One more time. How come? Where is the Okay, >> the call stack. It's yeah, it's it's when it calls it's almost fully surrounded and then it calls get stone. >> Unfortunately, it doesn't say the what the X or Y value is, >> but I wish it >> get stone returned like an like an edge over edge and then it wouldn't break >> and then it's not and it's not white and it's not black. [\[37:40\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=2260s) >> That's one way to solve it. >> That's interesting. like basically if x is all right for now just for us is if y is smaller than zero or is it one? Yeah. One. One. Yeah. [\[38:11\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=2291s) >> Return. You know what? Let's just say empty. >> No, no. Edge. Edge is good because empty would mean like it's empty position. So like anything we do the edge. Well, we can do empty right now and then we'll just add that feature later on. >> I just want you to notice that all the tests are passing now, >> right? Right. >> All right. We'll just keep this for now and then >> You're welcome. >> Thank you. [\[38:41\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=2321s) >> but yeah, but you can change it to edge. >> All right. >> And then we can do a test that says we need to check for X as well. But >> for now, >> so what did we just do? What feature did we just add by the way? >> vert vertical Okay, sounds cool. >> That's cool. >> Let me add in a todo. [\[39:13\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=2353s) >> Yep, I think that's good. >> All right. All right. >> Commit. Push. >> Commit >> and pray that nothing fails on my machine tomorrow. >> All right. >> Okay. >> >> let's see. Commit added vertical to surround two opposite color stones in vertical mode. Okay, that's good. Virtual. Virtual. >> Yeah. Nice. >> All right. >> Okay, Raymond. >> I forgot I forgot to >> Yeah, sure. [\[39:46\]](https://www.youtube.com/watch?v=8gP8lAMjzQg&t=2386s) >> Cool. >> I'll see you in session number 1 million35. >> Okay. Cheers everyone and hopefully you've had a better time than us. >> Cool. Okay, now it's stopped. Let's see if it actually ## Related - [Use parameterized tests to remove duplication](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_163) · The Art of Unit Testing, 3rd ed., ch. 8 Book section on parameterized tests to remove duplication, fitting the extra surround cases added here. - [A real bug has been uncovered in the production code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_136) · The Art of Unit Testing, 3rd ed., ch. 7 Book section on tests uncovering a real production bug, as new cases expose out-of-bounds errors at the top edge. - [What Algorithms should you test and how?](https://osherove.com/blog/2005/4/5/what-algorithms-should-you-test-and-how.html) · osherove.com Roy on which algorithms to test and how, relevant to test-driving the board-scanning algorithm. ### Also linked in this lesson #### osherove.com - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) [Previous lesson The Big Refactor](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/the-big-refactor/) [Last lesson Back to the course overview](https://courses.osherove.com/courses/tdd-pairing-sessions-building-a-go-game/) --- title: "TDD in .NET in Hebrew" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/" tags: [] author: "Roy Osherove" description: "TDD in .NET in Hebrew: 22 lessons, 7 h 44 min. A free video course by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # TDD in .NET in Hebrew [Courses](https://courses.osherove.com/#courses) 22 lessons 7 h 44 min 5 sections Spoken in Hebrew [Start course](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/introduction/) [Watch on YouTube playlist](https://www.youtube.com/playlist?list=PLU3Kucv9hL0o) ![](https://courses.osherove.com/img/yt/gtRXDuLj8uc.jpg) Recorded live during a 3 day course in Tel Aviv, Israel ## About this course Over three days, Roy Osherove teaches [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") and [test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") in .NET with [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)"), starting from the definition of a [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") and a calculator built test first. The second day covers [handwritten fakes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec3 "A simple handwritten mock example (The Art of Unit Testing, 2nd ed., ch. 4)"), [mocks versus stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_79 "The importance of differentiating between mocks and stubs (The Art of Unit Testing, 3rd ed., ch. 4)"), [isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99 "Defining isolation frameworks (The Art of Unit Testing, 3rd ed., ch. 5)") from [Moq](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5 "Current isolation frameworks for .NET (The Art of Unit Testing, 2nd ed., ch. 5)") and [NSubstitute](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html "FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition? (osherove.com)") to [Typemock Isolator](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html "Minimizing unit Test Fragility – 8 features in Typemock Isolator to help (osherove.com)"), and [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") for static dependencies. The third day turns his practices for readable, [trustworthy](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7 "Trustworthy tests (The Art of Unit Testing, 3rd ed., ch. 7)") and [maintainable tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)") into reviews of open-source tests and applies [refactorings](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec4 "Refactoring your design to be more testable (The Art of Unit Testing, 2nd ed., ch. 3)") such as instance delegator to the legacy BlogEngine.NET project. ## Related reading - [The pillars of good unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8) · The Art of Unit Testing, 2nd ed., ch. 8 From the lesson [Unit Testing Best Practices](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/unit-testing-best-practices/): The pillars of good unit tests: trustworthy, maintainable, readable, the three groups the lesson organizes rules into. - [Isolator feature focus: Recursive Fakes](https://osherove.com/blog/2008/10/4/isolator-feature-focus-recursive-fakes.html) · osherove.com From the lesson [Recursive Fakes](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/recursive-fakes/): Roy's post on Isolator's recursive fakes, the feature the lesson shows with NSubstitute and credits to Isolator. - [Issues in breaking dependencies for unit testing](https://osherove.com/blog/2005/8/23/issues-in-breaking-dependencies-for-unit-testing.html) · osherove.com From the lesson [Refactoring- Introduce Instance Delegator](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/refactoring-introduce-instance-delegator/): Roy on breaking multiple dependencies in an existing class or method, the situation with the static ping Manager. - [Mock Objects vs. "Inherit & Override"](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html) · osherove.com From the lesson [Legacy Refactoring intro](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/legacy-refactoring-intro/): Discusses overriding a virtual method in a test subclass, the extract and override technique taught here. - [First steps with NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 2 From the lesson [Syntax](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/syntax/): First steps with NUnit, the framework the lesson installs and whose TestFixture and Test attributes it explains. ## Curriculum Section 1 ### Day1 - Unit Testing and TDD 101 6 lessons · 2 h 41 min The first day defines a unit test as a check of a unit of work, from a public entry point to a return value, state change or third-party call, and explains why test suites fail when they are untrustworthy, hard to maintain or unreadable. Roy Osherove introduces the xUnit frameworks and NUnit, test naming and structure, and builds a calculator with tests in Visual Studio with ReSharper, NuGet and TestDriven.NET, covering TestCase, exception asserts and continuous test runners. The day ends with a calculator memory feature written test first and a preview of mocks and stubs. 1. [Introduction Duration 33:07](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/introduction/) Roy Osherove lays out the three days (unit testing basics, mock objects, legacy code) and separates unit testing, how to write tests, from TDD, when to write them. He asks why teams with many tests still give up on them: tests that check nothing, tests that cost too much to maintain, and unreadable test names. He defines a unit as a unit of work that starts at a public method and ends in a return value or exception, a state change, or a call to a third party such as a logger. 2. [Syntax Duration 29:43](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/syntax/) Roy Osherove argues that unit tests and integration tests complement each other, then introduces the xUnit family of frameworks, from SUnit through JUnit to NUnit, which the course uses, and its competitor MSTest. He explains the arrange, act and assert parts of a test, the TestFixture and Test attributes the runner finds through reflection, a three-part test name separated by underscores, putting the expected value before the actual one, and one logical assert per test. He starts a calculator class library in Visual Studio with ReSharper, adds a separate test project and installs NUnit with NuGet. 3. [Test Demo Duration 34:54](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/test-demo/) Roy Osherove shows where NuGet comes from and writes the first calculator test with ReSharper, explaining why he picks plain inputs such as 1 and 2 over numbers like 1337 that make a reader wonder. He prefers the TestDriven.NET runner, maps a keyboard shortcut to rerun the last test action, and runs any method under the debugger without a test. He adds a test for negative numbers, keeps random values and logic out of unit tests, and replaces the SetUp method with a factory method so each test stays readable on its own. 4. [Test Cases, String Asserts and more Duration 34:49](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/test-cases-string-asserts-and-more/) Roy Osherove merges similar tests with NUnit's TestCase attribute and compares ways to test an exception: try/catch with Assert.Fail, the ExpectedException attribute, which can pass when another line throws, and Assert.Throws with a lambda. He treats a TearDown as a sign of an integration test, to be kept in a separate project, and names the continuous test tools AutoTest.NET, NCrunch and Mighty Moose. He then introduces the three TDD steps and starts a calculator memory feature test first. 5. [TDD Demo Duration 19:26](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/tdd-demo/) Roy Osherove builds the calculator's memory feature with TDD: first a failing test, then the simplest code that passes all tests, which he describes as code with as many assumptions as possible, near the top of the function and with few ifs. The group designs the API through the tests, and he writes future tests down as comments so there is one problem to solve at a time. He also answers questions on organizing many tests, given/when/then in behavior driven development, and setup methods. 6. [Summary Day 1 Duration 8:45](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/summary-day-1/) Roy Osherove notes that by the end of the first day most participants were writing the test first and arguing about implementation, design and readability rather than whether to test at all. He previews the second day: replacing the console earlier was a kind of mock object, the difference between a mock (which the test asserts against, one per test) and a stub (any number per test), and frameworks such as NSubstitute. He asks everyone to redo the string calculator exercise from scratch for ten to fifteen minutes every morning so they do not forget what they learned. Section 2 ### Day 2 - Mock Objects and TDD 5 lessons · 1 h 51 min The second day opens with participants' questions about UI testing, storage and asynchronous code, then moves to fakes: a handwritten fake logger and web service passed in through the constructor, and the difference between a mock, which the test asserts against, and a stub. Roy Osherove compares constrained isolation frameworks such as Rhino Mocks, Moq, FakeItEasy and NSubstitute with profiler-based ones such as Typemock Isolator, rewrites the same tests with several of them, and shows recursive fakes. 7. [TDD Q & A Duration 35:14](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/tdd-q-and-a/) The second day opens with participants' questions. Roy Osherove suggests adding a command-line step that runs the tests in the build and fails it, and on UI testing contrasts recorded WinForms tests with Ruby's Capybara, which can run headless and test JavaScript, while recommending page logic such as validation be extracted into classes that unit tests cover. He keeps DateTime.Now, random numbers and threads out of unit tests, gives three ways to test code that ends in storage or a request (abstraction, a fake, or an integration test), and advises using mock objects as little as possible. 8. [Mocks and Stubs Duration 24:52](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/mocks-and-stubs/) Roy Osherove explains why a test replaces a dependency, using a manager class whose save method calls a logger that may be unfinished, buggy or slow. He adds a logger interface passed through the constructor and a handwritten fake logger in the test file; a fake is a mock when the test asserts on it and a stub otherwise, as in a second test where a stub logger throws and a fake web service is asserted. He advises one mock per test and no logic in fakes or tests, and shows NCrunch running tests in the background. 9. [Isolation Frameworks Duration 34:31](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/isolation-frameworks/) Roy Osherove explains that isolation frameworks generate fakes in memory that return values, throw exceptions and verify calls, and that any fake is a mock if the test verifies against it and a stub otherwise. He splits .NET frameworks into constrained ones such as Rhino Mocks, Moq, FakeItEasy and NSubstitute, which can only fake virtual or interface methods, and profiler-based ones such as Typemock Isolator, JustMock and Moles, which can also fake static methods. He then rewrites the logger tests with NUnit's basic dynamic mocks, Rhino Mocks and Moq, comparing string method names with lambda expressions, strict and non-strict mocks. 10. [Advanced Mocks and Stubs Duration 12:50](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/advanced-mocks-and-stubs/) Roy Osherove continues with Moq, showing callbacks, Verifiable and VerifyAll, and overriding protected methods, and warns that verifying many interactions you do not care about is overspecification, explained with a story about sending his son to buy pizza. He then writes the same logger tests with FakeItEasy, whose API starts with A and whose error messages he finds better than Moq's, and with NSubstitute, and recommends starting with one of the newer frameworks. Asked about profiler-based frameworks, he says they run slower but are used to get coverage on legacy code before refactoring. 11. [Recursive Fakes Duration 3:10](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/recursive-fakes/) With NSubstitute, Roy Osherove shows recursive fakes: when a person object is faked, its manager property returns a fake as well, instead of each returned object being set up on its own line. He says Isolator was the first framework to do this and that it makes tests more maintainable, because a new property or method that returns an object is faked by default. He then sends the group back to the exercises, up to the login manager that uses a static method. Section 3 ### Day 2 - Legacy Code Tools 4 lessons · 52 min This section deals with dependencies that cannot be passed in through a constructor: extract and override for a static logger and the machine name, a settable system time class for the current time, and Typemock Isolator for faking static methods, future instances and non-public members without changing production code. It ends with a preview of the third day's legacy project. 12. [Legacy Refactoring intro Duration 16:23](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/legacy-refactoring-intro/) Roy Osherove turns to dependencies that cannot be injected through a constructor, such as a call to a static logger, and introduces extract and override from Michael Feathers' book Working Effectively with Legacy Code, which he recommends. He moves the call into a protected virtual method with no logic and has a testable subclass of the login manager override it and save the text in a public field for the test to check, noting that in real legacy code he would first have an integration test in place. To concerns about exposing such methods he answers with internal methods and InternalsVisibleTo. 13. [Controlling Time Duration 6:44](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/controlling-time/) Roy Osherove applies extract and override to the machine name as well, then explains why it does not suit time, which is used throughout a system. Instead he adds an API to a central system time class so tests can set the current time, and resets it after each test because the change is static and affects other tests. He argues that a static class is not bad design in itself, suggests making the setter internal and visible to the test assembly, and sends the group to implement it in the exercises. 14. [Working with Typemock Isolator Duration 26:41](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/working-with-typemock-isolator/) Roy Osherove shows Typemock Isolator, a profiler-based framework for code that cannot be refactored: its API starts with Isolate, it can fake any class, including ones with private constructors, and it verifies calls with any or exact arguments. He explains the Isolated attribute that cleans up static fakes after each test and the profiler environment variables that Visual Studio plugins and command-line runners set, as Moles and JustMock also need. He then fakes static methods, future instances and non-public members without touching production code, mentions SilverUnit and CThru, which he built on Isolator, and asks the group to test the original exercise code this way. 15. [Day 2 Summary Duration 2:23](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/day-2-summary/) Roy Osherove previews the third day: the group will take an open-source project that has no tests and is mostly static and write tests for it both without and with Isolator, learning another refactoring technique on the way. They will also turn the practices discussed so far into a more formal set of things to look for, review tests from open-source projects, and, if time allows, write tests for the participants' own code. Section 4 ### Day 3 - Unit Testing Practices 4 lessons · 1 h 36 min Roy Osherove formalizes his rules for tests that are readable, trustworthy and maintainable: keep unit and integration tests apart, review tests first, and avoid logic, magic numbers, dependencies between tests and overspecification. He applies them in reviews of real tests from Microsoft's Unity, ASP.NET MVC and NerdDinner, and closes with ordering tests so that each changes only one input. 16. [Unit Testing Best Practices Duration 35:00](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/unit-testing-best-practices/) Roy Osherove groups his rules into tests that are readable, trustworthy and maintainable, and tells how a bug in a test helper cost him and a pairing partner 90 minutes on a Go engine built with TDD. For trust he separates unit tests from integration tests that need configuration, so a failing unit test is never "fine", and recommends code reviews that start from the tests. He argues that code coverage means little without reviews, then reviews a test from Microsoft's Unity source that has no expected behavior in its name, a loop and several asserts, and prefers readability to removing duplication. 17. [Best Practices Continued Duration 25:20](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/best-practices-continued/) Roy Osherove advises against tests that depend on each other's order and against magic numbers such as a 37 in the Unity tests, preferring the simplest value or a named variable. He shows an ASP.NET MVC test helper that builds a fake HTTP context with Moq and is full of ifs, suggests overloads instead, and wants expected values hard-coded rather than computed, so a production bug is not repeated in the test. Reviewing a NerdDinner test named "should be valid when all properties correct", the group debates splitting it into one test per validation rule. 18. [Maintainability Practices Duration 34:43](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/maintainability-practices/) Roy Osherove ties maintainability to a unit of work that runs from a real entry point to an end result, calling checks on how things are done overspecification, and wants isolated tests that can run in any order. He reviews an ASP.NET MVC test that loops over link overloads, which hides which overload failed, and a Moq test with two verifies where the data provider should be a stub. On readability he covers project conventions, a NerdDinner test with an unexplained 6, and a fake membership provider whose secret input protocol belongs in public constants. 19. [Readability Practices Duration 1:23](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/readability-practices/) Roy Osherove recommends ordering tests so that each one changes only one thing in the inputs compared with the test before it, such as one more character in a string, which makes the pattern readable and shows how the feature was built step by step. He sums up his three pillars, tests that are easy to read, easy to maintain and trustworthy, and calls TDD almost the only way he knows to see tests both fail and pass, though bugs in tests can still mislead. Section 5 ### Day 3 - Legacy Code 3 lessons · 44 min The last section works on BlogEngine.NET, a blog engine with acceptance tests but no unit tests: the group first gets its tests to pass, then makes a static manager class that sends pings and trackbacks testable with the instance delegator refactoring. The closing discussion covers how much code to include in a unit of work, when to fake, and testing private methods, and each pair writes tests for real production code. 20. [Legacy BlogEngine Project Overview Duration 8:02](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/legacy-blogengine-project-overview/) Roy Osherove introduces the legacy project for the third day, the BlogEngine.NET blog engine, which has no unit tests but has integration and acceptance tests. Some are written with WatiN, which is based on Ruby's Watir and works mainly with Internet Explorer, and others in a framework whose tests are written in Razor pages that run in the browser; of 20 tests, five fail. The exercise is to understand why and make all the tests pass, get to know the code and its dependencies, and try writing a new test before refactoring. 21. [Refactoring- Introduce Instance Delegator Duration 17:36](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/refactoring-introduce-instance-delegator/) Roy Osherove sets out to test the static Send method of a class named Manager in the ping namespace, which sends a trackback or ping for the links in a post or comment, and suggests finding its dependencies by calling it and seeing where it fails. The calls that send a trackback or ping are the end results, and the tests should prove the loop and each if. Because the class is static, he introduces instance delegator: remove static from the class, move the logic into an instance method that the static method calls on a new manager, then extract and override settings such as the trackback check in a testable subclass. 22. [Summary and Discussion Day 3 Duration 18:48](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/summary-and-discussion-day-3/) Roy Osherove explains that a fixture setup runs once before all tests and usually means something slow is initialized, and agrees that the refactorings made the code more testable, not better designed. On whether to fake the method that parses the links out of the content, he prefers to keep as much code in the unit of work as stays fast, in memory and readable, fakes threads, processes and the file system, and calls the choice the art of unit testing; a debate on testing private methods follows. Each pair then writes two or three tests for real production code that go into source control. --- title: "Introduction" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/introduction.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/introduction/" tags: [] author: "Roy Osherove" description: "Lesson 1 of 22 in TDD in .NET in Hebrew (Day1 - Unit Testing and TDD 101), 33:07. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Introduction 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day1 - Unit Testing and TDD 101 Lesson 1 of 22 Duration: 33:07 [Watch on YouTube](https://www.youtube.com/watch?v=gtRXDuLj8uc) Spoken in Hebrew ## In this lesson Roy Osherove lays out the three days ([unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") basics, [mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)"), [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)")) and separates unit testing, how to write tests, from [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)"), when to write them. He asks why teams with many tests still give up on them: [tests that check nothing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7 "Tests that don’t assert anything (The Art of Unit Testing, 3rd ed., ch. 7)"), tests that cost too much to maintain, and unreadable [test names](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html "Naming standards for unit tests (osherove.com)"). He defines a unit as a [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") that starts at a public method and ends in a return value or exception, a [state change](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec7 "Testing results that are system state changes instead of return values (The Art of Unit Testing, 2nd ed., ch. 2)"), or a [call to a third party](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)") such as a logger. ## Transcript 4,713 words [\[00:03\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=3s) כמה אנשים פה יש ניסיון עםסים אוקיי למי יש ניסיון עם obקטס דברים כמוס בערך בסדר כמה אנשים שמעו בכלל testing כמה אנשים חושבים שזה רעיון טוב יופי מצוין כאילו מין שאלה כזאת מוזמינת אבל תכף נדבר אם זה באמת רעיון טוב או לא משה מתכוונים כל הסיידים שאתם תראו פה אפשר להוריד בPDF אחד גדול פשוט תלכו הURL הזה ותורידו את זה. אני נסה לא להרוג עקסים כמה שאפשר. [\[00:36\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=36s) חוץ מזה מרבית הקורס הזה הוא בכלל לא סליידים אלא מרבית הקורס הוא כל כך קידוד. אז כאן אני אסביר לגבי השלושה ימים היום זה יום שמדבר על unit testingd ברמת הביסיקס בלבד. אנחנו לא נכסה מ objects בכלל אבל המון המון נכסה נושא של מה זה לכתוב testים טובים מבחינתability וust. שלושה דברים שהם חשובים שבעדיהם כל הנושא של יניטestינג בארגולים נכשל כמובן נכסה את כל הרעיון של מה זה יestיננו שמישהו שמעולם לא כתב unitטest בחיים שלו יוכל להתחיל את הקורס הזה אז גם אם בחיים שלכם לא כתבתם שורה של קוד עם משהו כמו [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)") או MSTest בסדר גמור והקורס הזה לא מניח שום הנחות את הדיטה שלכם אז אנחנו נצח ברמה מסוימת שמי שכבר יש לו ניסיון בהתחלה יחשוב שזה קצת טיפ טיפה מוכר אבל במהלך זה גם נכסה המון דברים המון prctices גם בטestטים הכי הכי פשוטים אפשר לכתוב אותם בצורה מאוד גבוהה אנחנו נתחיל לחסות את הדברים שגורים לטסestינג להצליח בא הרבה פעמים יוני testing אני לא יודע למה יש חברים שניסו [\[01:36\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=96s) לעשות יוני testing ונכשלו אבל זה קורה המון אנשים מנסים לעשות יוניט testing לי זה קרה בפרויקט הראשון שלי שאחרי שישה חודשים בערך התחלנו בעצם למחוק יוניטestים בגלל שכל פעם ששימינו את החוד היוטestטים התחילו להתפרק לנו התחילו ליפול ובשו שלב העלות והתועלת כבר לא היו שוות ואז התחלנו כבר להגיד אוקיי אז כל ההשקעה הזאת הייתה די לשב והתחלנו למחוק טestטים אז הרבה מהשיעורים שאתם תראו פה זה דברים שנלמדו בדרך הקשה כן כל החוקים האלה נכתבו בדם וכולי וזה ממש ככה זה ממש היה המון שיעורים מאוד קשים על איך לא לעשות ואיך כן לעשות [\[02:15\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=135s) אני אישית עובד בנושא של יונטסing וtvd 10 שנים בערך תשע שנים התחלתי בVB5 וV6 שש עוד אז היו כבר פריורקים ליוטesting וניסיתי אותם וכבר אז כתבתי דברים בצורה מאוד גרועה אבל למדתי בדרך אז I say you don't have to אבל [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1 "Defining unit testing, step by step (The Art of Unit Testing, 2nd ed., ch. 1)") [tdd](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6 "Test-driven development (The Art of Unit Testing, 2nd ed., ch. 1)") הם שני דברים שונים הרבה פעמים אנשו אומרים שהם עושים TDD אבל הם עושים unit testing הם לא עושים test driven and development אז יש פה שני פסטים שונים אנחנו נלמד את שניהם [\[02:50\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=170s) Unit testing זה האקט של כתיבה של הטestינג איך כותבים אותם וזה הסקיל של איך לכתוב אותם כמו שצריך. TDD זה מתי אתם כותבים את הטestים ואיך אתם משתמשים בהם כדי לדחוף את המוצר. ‏test dream development זה הרבה פעמים מדברים על זה שכותבים את הטestטים לפני הקוד אבל זה אבל אנחנו בהתחלה בחצי הלשון שלהם לא נתמקד בכתיבה של הטסטים לפני הקוד בכלל נתמקד באיך לכתוב אותם אחרי זה נראה איך הכתיבה שלהם בפני הקוד איך היא משפרת ומה היא עוזרת וכולי אבל הרבה פעמים הנושא של tdtd וני testing אנשים מחברים אותם ביחד חשוב שתבינו שאפשר לכתוב testים גם test first והם יהיו מאוד מאוד גרועים אוקיי וגם אפשר לכתוב testים שהם כתובים אחרי הקוד והם יהיו מאוד מאוד טובים לשני סקיל שם שהם לא קשורים חדשים. [\[03:33\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=213s) יש סקיל אחד נוסף שאני לא מלמד בחוץ הזה וזה דזיין. הרבה אנשים מדברים על TDD ואומרים test driven design מי ששמע. וראינו שהטestטים עוזרים לעצב את הדיזיין של הקוד שלכם ותוך כדי אתם גם יכולים ליצור דיזיין של הקוד שלא חשבתם שבהתחלה יהיה לכם. אז אנחנו נעשה אולי טיפ טיפה מזה אבל אני לא הולך ללמי זignק conceptפט בקורס הזה. נושא של design patterns [solid principles](https://osherove.com/blog/2013/3/6/refactoring-string-calculator-with-solid-principles-in-mind.html "Refactoring String Calculator with SOLID Principles in Mind - Examples Needed (osherove.com)") של איך לתורק oנט כל כצורה שהיא compפונט בשביל זה יש זה סקיל נפרד [\[04:05\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=245s) ואחד הדברים שראיתי זה שהמון אנשים נכשלים בעולם של td בכלל מצפסיקים לעשות את זה כשמנסים ללמוד שלושה דברים בבת אחת שזה לכתובטest לכתוב אותם לפני שכותבים את הקוד וגם להתעקל בבעיות דיזיין תוך כדי זאת אומרת איך לעשות את הדברים את הדיזיין בצורה הכי טובה אם אתם מנסים לעשות את שלושת הדברים האלה מבת אחת הרבה פעמים נכשלים בגלל שהקיר הוא גבוה מדי. אתה מנסה לכתוב את הטest הראשון שלך ופתאום את צריך לעשות את שלושת הדברים האלה בבת אחת. ואם אתה לא יודע לעשות אף אחד מהם עדיין אז ללמוד אותם תוך כדי עשייה של משהו שאתה עדיין לא יודע זה דבר הרבה יותר מסובך. [\[04:39\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=279s) אז אנחנו הולכים לעשות את השניים הראשונים. לכתוב testing ואז ללמוד לכתוב אותם test first person. 50% מהקורס הזה הם קידוד. זאת אומרת שבחצי השני של היום רוב מה שתעשו זה קידוד. אתם תהיו בעיקר בחברים האלה. אבל בחצי הראשון אני הולך להראות בעיקר איך לכתוב את הטestינג וגם איך נראית הסביבה שלי בתוך סטודיו איך נראית סביבה של מישהו שרוצה לעשות TDD זאת קונפיגורציה אחת של הסביבה אני אראה לכם גם הרבה כלים שחלקכם אוהבים חלקכם לא אוהבים זה גם בסדר אני אראה לכם את הדרך שלי לעשות את זה ואני גם מסביר למה [\[05:13\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=313s) אני אוהב את הדרך הזאת זאת אומרת לכל דבר תהיה סיבה ואם יש לכם שאלות אז זה אין לי שום בעיה שזאת תהיה שיחה ולא הרצאה אמ אני גם מסביר הרבה קונספטים שקשורים לאוטומציה ואטומציה של ויזואל סטודיו בגלל שאני מאמין שכמתכנתים כאנשים מקצוענים אנחנו צריכים להכיר את הפילים שלנו בצורה הטובה ביותר פשוט להכיר את כל ה את כל היכולות שלהם או את רוב היכולות שלהם אה יש פה מישהו שמשתמש ברישרטה אוקיי מי אוהב את רישאר מהמשתמשים [\[05:46\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=346s) יודע יש פה ליססים לקנות כולם התקינו טרייל אוקיי אנחנו נשתמש בריאפר הרבה כי אני משתמש בו לtvdd אמ לדוגמה אם רוצים להכיר את רישפר זה להכיר את רוב השורטקאטים שלו את כולם להכיר את היכולות שלו ומתי אפשר לעשות מה אז אנחנו נכנס גם לכמה פיצ'רים שלו שעוזרים בתהליך שלv בתהליך של כתיבת הטestטים עוד ניכנס בהמשך היום גם לכלים של continous test שעוזרים לנו להריץ דברים בטd אבל בצורה שהיא כמעט בלתי נראית לעין בלי שני אצטריך לעשות הרבה עבודה [\[06:21\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=381s) אוקיי אז הקונספט קר קודם כל הקורס הזה נקרא tdd בגלל שכל כל הקידות שאתם תעשו בקורס מלבד השעה אוניה הראשונה או השנייה שלכם היום יהיו test first גם הדברים המסובכים ביותר אתם תנסו לעשות דברים test first ביום השני אנחנו נדבר על [מוק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4 "Interaction testing using mock objects (The Art of Unit Testing, 2nd ed., ch. 4)") objects וניכנס לטestטים הרבה יותר מסובכים ממה שאנחנו כותבים היום הרבה פעמים אנשים אומרים שהיום הראשון זה היה יום קצת פשוט והכל די בסדר ונו ציפיתי ליותר אז ביום השני יש עלייה ת מדרגה מאוד גבוהה ואז אנשים אומרים או כן בסדר זה מה שרשיתי אבל אי אפשר לעשות את היום השני בלי היום הראשון חשוב שתבינו שהביסיקס האלה הם מאוד חשובים [\[06:58\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=418s) אז נלמד המון best practices במק וגם את זה נעשה testing ביום השלישי ניכנס ללגס קוד ונראה איך כותבים testingים לקוד קיים כולל רפקטורing וגם מה קורה שאי אפשר לעשות רפקטורים אז אשתמש בקליפ כמו כדי לכתוב טestטים לקוד קיים בלי לשנות אותו כדי שתוכלו לראות שיש אופציות תמיד אפשר אפשר או להשתמש בכלי או לעשות ריפת כל גם בלגסי קוד אפשר לעשות דברים שהם test זאת אומרת אם מצאתם איזשהו בג קודם כל כותבים את הטest שמוכיח שיש בג ואז פותרים את הבג ואז רואים שהטestט עובר אז testן זה לא רק לקוד חדש זה גם בהחלט יכול להיות לקוד קיים או תיקון של קוד קיים יותר נכון [\[07:40\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=460s) אוקיי אמ כמה צרטים יש פה דרך אגב שלושה שושה צבטים אתם גם יושבים כרגע לפי הצבטים שלכם אחד לשני אנחנו בט לא מתערב >> יש צוות אחד שיושב למעלה או שכולם יושבים פה בחומה הזאת >> אחד שישב למעלה אבל היום לצורך הזה אנחנו כולנו יושב למעלה >> אוקיי אוקיי אז test development הוא prctice אחד שבא מעולם האxtream praming exream prraming אני מניח שובכם כבר שמעתם את של extraming מה שיפה בtd שאפשר לקחת את הrac הזה כמו שהוא ולעשים שים אותו בכל מתודולוגיה הוא לא קשור למתודולוגיה [\[08:21\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=501s) זה משטיס שהוא בן אדם למחשבות תחשבו על זה ככה אף אחד לא יכול להגיד לכם לכתוב testing כי זה החלטה שלכם כמו שאף אחד לא יכול להגיד לכם לעשות דבג למשהו זה החלטה שלכם איך לעשות איך לכתוב קוד ולכן גם אם אתם יודעים בעולם הוורטרפול הכי גדול שיכול להיות נגיד אמדוקס אתם עדיין יכולים לעשות DVD בגלל שזה החלטה שלכם לכתוב את הטestטים מה קורה אחרי זה האם יש איזשהו בילס ו שמריץ את הטestטים אלה כבר דברים שמשפיעים על הקבוצה על על ההחלטה על ההרגשה איך זה לעבוד בתור קבוצה [\[08:55\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=535s) אבל בכל ארגון אתם יכולים להיות הבן אדם שמתחיל את הדבר הזה ושמריץ את כל הטestטים שלו לפחות אישית לפני שהוא כותב את כל פעם זה חשוב כי בכל הרבה פעמים יש הרבה התנגדויות לדברים גם אנשים ששמעו על יוניטסing הרבה פעמים חושבים שזה לא מכחות וצריכים להרגיש באמת עוזר ואחד הדרכים לדחוף את זה זה להראות תוצאות אז כדי להבין מה זה TDD צריך כדי להבין מה זהIT testing צריך להבין מה זהIT test זאת ההגדרה של הITEST מויקיפדיה [\[09:30\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=570s) הגדרה חלקית a test of a small function of cod יש לנו פונקציה is login אוקיי שמקבלת user וורד אז unit test יהיה חתיכת קוד אחרת שמפעילה את החתיכת קוד הזאת אוקיי אמ עכשיו לפני שיכנס להדר שלטסט כמה לדעתכם טסטים אפשר לכתוב לפונקציה הזאת בלי שאנחנו יודעים בכלל את הפונקציונליות שלה מה המספר המינימלי של טestטים אה >> ארבע איזה testing user password not user password [\[10:04\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=604s) >> ואז password user not password user not >> אז זה כבר לא יותר מארבע >> אה חשבתי ש אה אתה רוצה טestט אחד עם שני אלה לנלים טestט אחד עם אחד נעל ואחד לא אוקיי ואז >> טestט שלישי השני נעל והראשון לא >> אוקיי >> והראשון שש שניהם לא >> אוקיי יש למישהו עוד רות אני לא >> אני חושב שזה כאילו תלוי במה מה הפונקציה הזאת עושה כלומר יכול להיות שם >> לכל פונקציית לוגן שמקלת שני פרמטרים זירה בול מה תסים המנירים של רוב הסיכויים שיהיה לך >> לפי התרחישים שמתמולדת בהם למשל אם יש יוזר קיים אז אני צריך גם לעשות בדיקה שאם היוזר הזה קיים אז לעשות את זה גם כב >> אוקיי אז לא user נעל אלא user שהוא [\[10:48\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=648s) Does not exist אוקיי >> למשל השם של הזר לצורך הנון הוא לא חוקי לדוגמה >> שם של הזר הוא לא חוקי אוקיי >> אוקיי בעצם לפי כמות >> כן לדוגמה >> אוקיי >> >> אז כמה כבר הגענו חם אנחנו הולכים על שש >> שבע >> שבע אוקיי אז בואו רגע ננסה סטטוס פה כמה אנשים חושבים כמה אנשים חושבים שצריך פה אה לפחות שלושה טestטים לפחות ארבעה [\[11:19\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=679s) חמישה שישה שבעה שמונה אוקיי לפחות שמונה טסטים רובה אנשים שפה חושבים שמונה טים אני דווקא אלך לקונסנוס הנמוך ביותר וזה היה ארבעה בואו נניח ארבעה ואנחנו נחיה עם ארבעה עכשיו בעינתן שלפונקציה הזאתי יש לוגיקה אנחנו בדרך כלל נכתוב נכתוב טסים לקוד שיש לו לוגיקה סוויץ כל הדברים האלה לולאות לא לכתובסטים ישירות לפרerטז שלא עושים שום דבר כי זה בדרך כלל סוג של בזבוז זמן [\[11:53\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=713s) כמה פונקציות עם לוגיקה יש לכם במערכת איןס >> וכמה שאלת מילה אתה רוצה אלים >> אלפים לא לפחות >> לפחות כמה אוקיי אני אני אקל לכם כמה publicקפ functionנקשנס אז אם לא יש לכם במערכת לא ממש אוקיי אז רק מספר יותר מ-500 יותר מ-5,000 מה >> הייתי אומר יותר מ1,000 >> יותר מ-10,000 אז כמה טestטים לפחות צריכים להיות לכם במערכת לדעתכם [\[12:28\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=748s) זה לא כולם מחזירות גוליה אני מניח לא כולם יש להם שני פרמטרים אבל אתכם בממוציה אחת שצריך להיות לה 200 טסים יכול שב על פונקציה אחת שצריך להיות רק ל 200 >> אוקיי איזה שנים >> אני ראיתי איזשהו אימיל שהסתובב פה על פונקציה שיהיה שמישהו פוחד של זה הפונקציה מדבר על הפונקציה >> אה אוקיי נראותה מאוד נחמדה הפונקציה >> יש עוד כמה כא >> זה דרך אגב הגדרה של הפונקציה הזאת זה נקרא גוד זה אתה לא יודע למה היא עושה מה שהיא עושה אתה רק יודע שתניח לה לנפשה והיא תעשה את מה שהיא צריכה אל תיגע אל תתערב מה שנקרא [\[13:05\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=785s) אמ אוקיי אז אנחנו מדברים פה על כמה כמה אלפי טסטים טובים לפחות או כמה 10,000 טestטים עכשיו אתם לא החברה היחידה שיש להם את כמות הפונקציות האלה נכון אתם גם לא החברה הכי גדולה שיש כלומר זה לא הקוד הכי הקודביס הכי גדול שראיתי מרבית החברות גם כשאני שואל את השאלה הזאת ויש להם טestטים אין להם אפילו קרוב למספר של טestטים שנלתם צריך להיות מינימלי ש את השאלה למה [\[13:36\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=816s) יש לכם רעיון למה חברות שגם שיודעות לעשות testing לא כותבות את כל הטסא של זמן >> שאלה של זמן אוקיי עצלנות צלנות >> אני לא חושב שמתכן תהיה מצ >> לחץ של זמן שתו >> לחץ של זמן זה תמיד לחץ של זמן שזה יהיהסית >> אוקיי לחץ של זמן זה מרכיב מאוד מאוד עיקרי אבל אני רוצה לפרק את זה לבעיה יותר לכמה בעיות יותר קטנות ואנחנו ננסה לדבר על הבעיות האלה והבעיות האלה בדרך כלל כשמדברים על יניטestטים אומרים אומרים [\[14:10\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=850s) או אם אתם ראיתם פעם הרצהים אומרים את הדברים האלה על unit test כשיש לי 10,000 יוניטestים בקוד יותר קל לי למצוא באגים נכון או לא נכון או מיי חושב שזה נכון מי חושב שזה נכון מי חושב שאולי זה לא נכון זה אולי לא נכון >> אולי לא נכון למה יכול להיות שהטסטים שלך לא בודקים כלום אוקיי יכול להיות שהטestים שלי לא בודקים יכול להיות שלטסestים שלי יש בדים כן איך אני אדע אם לטסט שלי יש בד אני טס הטest ואם הטסט טס של יש בה קורסיבי [\[14:42\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=882s) אז לא בהכרח מוצאים את הבאגים כשיש 10,000 טestטים בקוד וזה מאוד נכון הרבה פעמים אנשים כותבים את הטestטים והם לא כותבים את הטestטים הנכונים או הם בודקים את הדבר הלא נכון דווקא פה הנושא של test dream development לכתוב את הtest לפני הקוד מאוד עוזר כי כשכותבים את הטest לפני הקוד אני לא יודע אם שמה אתם מתחילים מטestט שנכשל ואז גורמים לו לעבור בלי לגעת בטestט ובצורה הזאת בודקים את הטest הוא אמור להיקשל ואז הוא אמור לעבור ואם הוא מתחיל בהתחלה בלי כישלון או שהוא נכשל אבל קמתם את הפרודקשן אבל הוא ממשיך להתקשב ולא עובר יכול להיות שמצאתם באג בטest עצמו וtd זה אחד הפרקטיס היחידים שאני מכיר שבאמת עוזר לך לבדוק את הטestטים שלך ולוודא שהם באמת נכונים בלי לכתוב טestטים לטestטים [\[15:30\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=930s) יותר קל לעשות maננס לקוד אם יש 10,000 testים מי חושב שזה נכון מי חושב שזה לא בכלל נכון למה >> כי כל >> כתבתזה חמישה לא >> כתבתי כן כי כל כי כל שינוי בקוד עכשיו אתה צריך לשנות פי חמש טestטים מהקוד ששניתם >> אוקיי אז אני אתן לכם את הדוגמה הכי פשוטה כתבתם 20 טestטים שיוצרים אינסטנס של איזשהו קלאס וקוראים לפונקציה על הקלאס הזה עכשיו הלכתם והוספתם קונסטרקטור לקס הזה עכשיו יש לכם 20 טסטים שלא מתקמנים צריכים לשנות אותם אחד זה הדוגמה הכי פשוטה וזה אחד הדברים שקורים הכי הרבה [\[16:08\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=968s) אז פתאום המייטנס של הקוד נהיה הרבה יותר גרוע לא הרבה יותר טוב אז כל הזמן שהטסם אמורים לחסוך לכם אולי בדיבגים או במציא באגים פתאום עולה לכם בזמן של מינס זה אחד הפיונים הכי מרכזיים שאנשים שקורים לאנשים להפסיק לעשות יני testing זה שכשהשינו של פרודקש קוד עולה הרבה יותר זמן בגלל שהטestטים דורשים תחזוקה גם במהלך הקורס הזה אנחנו נתמקד הרבה בלגרום לטסטים להיות הרבה יותר מנטינבילים כדי שהעלות הזאת תהיה כמה שיותר נמוכה. [\[16:41\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1001s) אם אנחנו לא נטפל בעלות הזאת אז הטestטים פשוט יאכלו לנו את את הזמן של הפרודקשן ולא יהיה שווה לעשות אותו. אז אם אנחנו לא עושים טestים שהם מינטינable לא שווה לנו בכלל לעשות טסים. פשוט ככה לא שווה לעשות אותם בגלל שאנחנו שלושות שים להתפתר מהם. אולי שווה לעשות כמה כמה inרation test ככה פה ושם מדי פעם זורקים ואז כותבים מחדש אבל ממש להיכנס לנושא הזה לא שווה כי הזמן שזה יעלה הוא הרבה יותר גבוה הרבה ארגונים נופלים דווקא בדבר הזה [\[17:12\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1032s) ובפרויקט הראשון שכתבתי אי פעם זה באמת הייתה הבעיה זאת אחת הסיבות שהתחלנו להיפטר מהטestטים ושראינו שהקוד מתחיל להרגיש כמו בטון שכל דבר שאתה מנסה לשנות יש 20 טestטים שאומרים שהוא צריך להראות בצורה מסוימת ועכשיו אי אפשר לשנות את הצורה הזאת ואנחנו נדבר על איך אפשר לפתור את הבעיה הזאת. ועוד דבר שאומרים על testי, יש לך 10,000 טestטים, יותר קל להבין את הקוד. וכשאומרים את זה, מתכוונים לזה שהטestטים סוג של executable specificק שאתה לוקח מתכנת חדש לצוות ואתה אומר לו הנה הקלאס והנה הטestטים, תסתכל על הטestטים ותבין איך הקלאס עובד. [\[17:50\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1070s) הרבה פעמים גם זה הדבר הזה בכלל לא נכון כי כשאנשים כותבים testים בהתחלה השמות שהם נותנים לטestטים הם test אחד test 1 שט test also שת וכולי לא אכפת להם בכלל מהשמות של הטestטים לא אכפת להם מהרדity של הטesting ואז הדבר הזה לא נכון בכלל אז אנחנו גם נדבר על הרדילטי של הטestטים ועל עד כמה הוא חשוב ואיך לגרום להם להיות יותר יותר רק אם שלושת הדברים האלה נכונים אז באמת קל יותר לפתח עם טesting אם אפילו אחד מהם לא נכון הוא משפיע על כל ה וכל החוויה הזאת נהיית הרבה יותר גרועה [\[18:27\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1107s) ו וביחד תיקחו כל חברה היום שאין לה אין לה את ה אין לה את הזמן לעשות טestטים או חברה שהתחילה והפסיקה היא תגיד לכם שזה קשור לאחת הסיבות האלה אבל הם יגידו עוד כל מיני דברים חלק יגידו אנחנו כבר עושים יוניטestטים אבל הם לא באמת עושים יניטסטים בהגדרה שלנו. זאת אומרת הם כל פעם בודקים בצורה ידנית. מישהו פה כתב אי פעםפור עם כל מיני טקסט בוקס וכפתורים בטן אד בטן שתיים. אם לוחצים עליהם בסדר הנכון אז יודעים שהכל עובד. [\[18:59\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1139s) אי פעם מישהו עשה את זה? אני עשיתי את זה. מישהו עשה את זה? אוקיי זה לוקח הרבה זמן ואתם היחידים שיכולים להריץ את הדבר הזה. אז ברגע שאתם כתבתם את זה ברגע שאתם לא משתמשים באיזשהו פריימורק אז הטestטים שלכם הם אינדיבידואלים. אינדיבידואליסטים לחלוטין. המטרה שלנו היא שהטestטים האלה הם יהיו repפatable שכל אחד יוכל לחזור עליהם. שהם יהיו מהירים, אבל גם אנחנו רוצים שזה יהיה על כל הקוד שלנו. הרבה פעמים אנחנו לא כותבים טסטים על כל הקוד שלנו בגלל שלוקח הרבה זמן לכתוב אותם בגלל שלא משתמשים באיזשהו פריימורק. [\[19:29\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1169s) אם היינו משתמשים בפריים הרבה פעמים יותר קל לכתוב את הטestטים בגלל שהפרימוקים מקלים עלינו. בפנים זה הרבה יותר קשה לכתוב את הטסטים בגלל שאין לנו את פרימו כזה בגלל שאנחנו צריכים להריץ אותם בצורה אוטומטית לעשות איזה איזשהו קומנדלי כדי להריץ אותם. אבל אני רוצה לחזור להגדרה של unit test מה זה unit [\[20:00\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1200s) ופה אנח אנחנו צריכים את הורד מה זה יוני דה לפני שאד חוזר מהם אזור בקוד >> מה >> אזור בקוד >> אזור בקוד אוקיי אז איפה האזור הזה מתחיל פה קצת מעל הפונקציה פולה את הספייס מעל הפונקציה אה אז יוניט משתנה בהתאם להגדרות שלך זה ניחוש >> אוקיי יש למישהו עוד ניחושים לא אומר שזה ניחוש לא נכון אה >> פונקציה >> מה >> פונקציה פעם חשבתי שזה פונקציה אתה צודק [\[20:37\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1237s) מהח של הטסט בודק >> מה >> החלק של הטסט של הפונקציה >> החלק של הקוד שאתה בודק החלק של הפונקציה >> החלק שלו >> כמה שהוא שרוקות בפונקציה אוקיי יש עוד אפשרויות קלאס >> קלאס לפעמים אתה בודק קלאס שלם עם כל הפונקציות שלו נכון אנחנו צריכים כן [\[21:17\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1277s) יכול להוריד את המחשפה זה בסדר >> זה לא מזל טוב או משהו הדבר הזה כנראה שלא >> יכולים למעלה למה למעלה זרוק אתה למעלה אותה לא >> אוקיי אז יכול להות פונקציה אה פשן x זה יכול להיות קס [\[21:50\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1310s) מהו זה יכול להיות תהליך >> תהליך מה זה תהליך פעולה מס פעולה של מי מתחיל כל אחד אתה תהליך דוח כל אחד זאת אומרת מפתח מתחיל אותה תהליך >> user אוקיי אז יוזר מתחיל איזשהו תהליך ואז מבחינת הקוד מה התהליך הזה כולל כלול את הקוד שקס עם הפרמטרים האלה הוא לא בהכרח הפונקציה כי הוא יכול להגיע לעוד פונקציות למטה >> אוקיי [\[22:21\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1341s) אבל הוא מחובר לאיזשהו סטייט איזשהו צריך איזשהו סטייט הוא יכול לכלול יותר מקלס אחד >> כן כן >> כן >> אוקיי שתיים בסדר יכול לכל יותר מפרויקט אחד התהליך הזה כןס מצוין אוקיי יש עוד איזשהו לבל יכול להיות מסיבt אחד לאסution אבל אסמלי [\[22:52\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1372s) יכול להיות אוקיי ומה ש בהתחלה כשאת בהתחלה כשרק נתקלתי בכשרק התחלתי אתITטסדנ כשכתבתי את הספר הספר דרך אגב התחיל להקדל לפני שש שנים היום אני כותב גרסה חדשה שלו שמתקנת הרבה מהדברים שפעם חשבתי אז פעם חשבתי שיוני זה היחידה הכי קצת נשפות שיש ללוגיקה זאת אומרת פונקציה אבל יש פונקציות שאני לא רוצה לבדוק יש הרבה פעמים פונקציות שהם prייט שאני לא רוצה לבדוק כי אם אני בודק אותם אז באמת הרוכות שלי נהיה כמו בטון מחר אני משנה אותה אני עושה לה רפקטורי [\[23:31\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1411s) ווכל הטestטים שלי נכשלים למרות שאולי בסוף הכל כות עושה את העבודה הנכונה אז התחלתי לחשוב מה זה אומר שאני יודע שמשהו בסוף עושה את העבודה הנכונה איך אתה יודע שמשהו בסוף עושה את העבודה הנכונה גם אם עשית ריפקטורים תוצאה חלפס >> תוצאה מה זה תוצאה איזה תוצאות יש הצלחה כישלון מה זה הצלחה כישלון הצלחה וכישלון זה משהו שאתה מחליט עוד קיבלת שלוש זה הצלחה או כישלון אוקיי אז איזה סוגי תוצאה יש לזה אני מתכוון [\[24:04\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1444s) אוקיי אלה שציפים שלנו זה מבחינת הטestטים אבל איזה סוגי תוצאה יש בקוד >> exceptפtion exceptפtion אוקיי אז אם יש לנו איזשהו יוניט בואו נחליט מה היוט הזה עוד לא נחליט מה זה היוט הזה יכול לזרות exception מה עוד valגם return valtion זה אותו דבר זה גם ס מה עוד שהוא קרה למשהו שהוא קרה למשהו [\[24:35\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1475s) אוקיי מה זה קרה למשהו לדוגמה לוגר או קלאס אחר אוקיי אדפט ומה עוד יש בדבס >> בדataביס ומה זה אומר מהו >> כן אבל הזה קרה i בסדר זה שינה משהו כן אבל מבחינת היוזר זה שינה משהו [\[25:07\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1507s) אז עשיתי משהו בעיות זה שינה משהו זה יש איזשהי תוצאה זה יכול להשקיע תהליכים אחרים פה זה יכול להשקיע תהליכים אחרים זה אומר שזה שינה איזשהו סטייט זה לא סתם היה הסטייט של המערכת משתנה המערכת מתנהגת אחרת אלה שלוש שלושה סוגי התוצאה שיכולות להיות על זאת אומרת פעם כשהייתי כותב testים לprvateטפש ואז הטestים שלי היו נכשלים שנית prvate function ידעתי שהטס סטים שלי טועים בגלל שההרגשה שלי הייתה שהמערכת בסופו של דבר עושה את הדבר הנכון אבל לא ידעתי להגדיר מה זה הדבר הנכון הזה היום אני יודע קצת יותר טוב להגדיר מה זה הדבר הנכון מבחינתי unit [\[25:45\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1545s) זה לא פונקציה unit זה [unit of work](https://www.artofunittesting.com/definition-of-a-unit-test "Definition of a Unit Test (artofunittesting.com)") זה סוג של באמת תהליך אבל זה תהליך שמותחל על ידי המשתמש או מיוצג על ידי איזשהו משתמש ולכן זה חייב להתחיל בפאבליק זה משהו שאפשר לעשות לו אז יוניט מתחיל באיזשהו פאבק והוא נגמר באחת מהתוצאות האלה או שהוא מחזיר valו או ש או שהוא משנה סטייט במערכת ואז הוא הולכת מתנהגת אחרת או שהוא קורא לאיזשהו פטי משהו שהוא לא בשליטתנו לדוגמה לוגר שצוות אחר כתב לדוגמה [\[26:22\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1582s) קוד בשרפנט שאני לא רוצה לגעת אחד אז יש לי התחלה סט ויש לי איזשהו סוף ואז כל הדברים שפה באמצע לא אכפת לי מהם בכלל לא אכפת לי אם זה פונקציה לא אכפת לי אם זה שלושה קלאסים לא אכפת לי אם זה 17 פרויקטים unit of work יכול להשתנה יכול להיות קטן כמו פונקציה יכול להיות גדול כמו כמה קלאסים [\[26:53\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1613s) מבחינתנו ההגדרה של unit test אני יכול לכתוב testים לסקופ כשהוא קטן או לסקופ שהוא גדול. הרבה מההחלטות או הרבה מהאומנות שאני רואה בדבר הזה זה ההחלטה באיזה סקופ לכתוב את הטestטים. אבל אני לא אכתוב testingים לדברים שהם prיט כי מבחינתי כל דבר שהוא prיט הוא חלק מunitive work אחר. כל פונקציה שהיא prיבט אצלכם בקוד יש לה סיבה שהיא קיימת. זאת אומרת מישהו קורא לה. אם אף אחד לא קורה לה אפשר למחוק אותה. היא לא צריכה להיות שם. אז הסיבה היחידה שהיא קיימת זה בגלל שמישהו קורא להבסופו של דבר המישהו הזה מותחל על ידי משהו שהוא פאבליק. [\[27:27\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1647s) לכל פונקציה קיים קיים לפחות סיבה אחת לפעמים היא יכול להות חלק ממile units of work שבגללה היא קיימת אז אני יכול למצוא דרך לבדוק את הפונקציה הזאת על ידי מציאת הUNIT of work הנכון והend resultלט הנכון ואז אני יודע שהכל בדרך עובד עכשיו זה הכוח האמיתי כשמדברים על מיity הרבה פעמים הבעיה של mainity קוראת בגלל שהטestים שלנו מגדירים יותר מדי מה צריך להיות פה בפנים אתה צריך לקרוא לפrivate fun הזאת ואתה צריך לקרוא ל קלאס הזה והקלאס הזה צריך לקבל שלושה פרמטרים ואתה קורא לביס קלאס שלך לא אכפת לי ככל שלא אכפת לי כמו שאני מתייחס לזה כסוג של הקופסה שחורה [\[28:07\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1687s) ורק אני מתייחס לשלושה אדריז האלה אז הטestים שלי הם הרבה יותר [maintainable](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)") בגלל שאז אני יכול לשנות פה הכל זמן שהאנדריזל אותו דבר הצestסטים שלי עדיין ימשיכו לעבור והם לא יכסו עליי על זה שגידו משהו שלא אכפת שלא אמור להיות אכפת להם אלו הרבה מהמטility problem היום קורים בגלל שאנשים אנשים עושים מה שנקרא overפication. הם בודקים דברים ש הם לא אמורים לבדוק. ככל שאני חושב על זה היום, צריך להתחיל במשהו שהוא פאבליק ולהיגמר במשהו שהוא publicקly visible. [\[28:38\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1718s) זאת אומרת משהו שהמשתמש יכול להרגיש. לדוגמה אם אני מכניס לדataביס אז עכשיו הלוגן שלי אמור להצליח, נכון? אני משתמש באותו API או בAPI אחר ועכשיו API אחר מתנהג אחרת. זה בסate change אבל או שאני מקבל value אחר או שאני מקבל אפtion אחר והטestטים הכי מסובכים זה הטestטים שקורים לרדd part אלה הטestטים אלה המקומות שבהם מתחילים להשתמש במק objects ובגדול כשמדברים על testים או על unit testים [\[29:09\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1749s) אני רוצה לוודא שהטestטים שלי שולטים בIT בצורה מלאה זאת אומרת שאני שהכל א' אני יכול לגרום לו לרוץ כמה שיותר מהר בדרך כלל זה אומר לגרום להכל לקרות בזיכרון אם יש לי איזשהו IO אז צריך שתהיה לי שליטה עליו לדוגמה להחליף אותו באמצעות משהו כדי לעשות פה מה שנקרא כדי להחליף אותו שאני נוכל לקנות את הטסט אבל לפעמים האנדרי resultלט שלי היחיד הוא לא שינוי סטייט ולא החזרת אלא פשוט איזשהו קריה ללוגר איפשהו [\[29:41\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1781s) נכון לפעמים צריך לקרוא ללוגר לפעמים צריך לעשות משהו שעושה לאנשו ואז המערכת השנייה כבר מטפלת במה קורה כשאתה מקבלטיפיקציות פה נמצא הנושא של הסד particני כשאני מחליט איפה הגבול בין המערכת שלי למערכת חיצונית בדרך כלל הגבול הזה עובר איפה שאין לך שליטה יותר זאת אומרת הקוד שלך לא יכול להחליט על ההתנהגות של המערכת או שזה נורא נורא מסובך להחליט אז אתה פשוט מחליף אותה באיזשהו מוקט משהו שנראה כמו מערכת החיצונית ואתה בודק שקריאה למשהו שנראה כמו מערכת החיצונית התקבלה [\[30:14\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1814s) וזה הסוג השלישי של הטסטן שבדקת האינטראקציה בין מערכות שאלות. כן. >> במקרה של עבודה עם עם דatבי במקרה שלנו clוד זה אומר שיש צורך לעשות תשתית נוספת שהיא עושה מוק לקוד וובעצם רב הטestטים בכלל לא צריכים לגשת לדטה עצמו. >> בקלאוד. זה נושא מעניין כי כי זה מאוד תלוי כמה שכבות יש לך מעל. [\[30:45\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1845s) אם אני מדבר על השכבות של אפליקציה הרבה פעמים בעיקר בעולם המייקרוסופט מדברים על זה שיש לך שלוש שלושה סוגי שכבות יש לך את הui יש לך את הBL ויש לך את הl ואז פה למטה יש איזשהו דabיס אוקיי בדרך כלל testים על UI לא שווה לי לעשות מבחינת הCOST versusס אעלות אות לא שווה לי בגלל שUI משתנה כל הזמן ואז הטestטים שלי כל הזמן צריך שנות פשוט אין דרך החוצה מזה כמעט אתה עושה testים על UI [\[31:19\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1879s) BL בדרך כלל הביזנסיק או הביזר זה המקום שבו עושים את מרבית היוטי דהר בעצם השכבה שמדברת ישירות עם הדביס או אצלכם מבחינתכם זה ישירות עם הקלאוד יש לכם איזשהיא אסטרציה מעל הקלאד זה מה שאתם ראיתם עכשיו הרבה פעמים באפליקציות שבה אם יש דטביס סטנדרטי אני לא בודק את הדataל ואני עושה [פייק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") לדataביס בגלל שהרבה פעמים הדביס עצמו מחיל חלקים מהלוגיקה. זאת אומרת המבנה של הדatביס הרבה פעמים הוא סוג של לוגיקה. [\[31:50\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1910s) טריגרים חלוקה בין טבלאות שהם כיעוד אחת בשנייה. פורנקי זה גם סוג של לוגיקה. ולכן גם אם הייתי בודק את הדבר הזה והייתי עושה לזה פייק אז זה שזה עובד לא אומר שהאפליקציה שלי עובדת. אוקיי? זאת אומרת חצי מהלוגיקה היכולות שנמצאת פה ואני לא בודק אותה בכלל. אז הרבה פעמים באפליקציות סטנדרטיות שיש דabס את הדatר עצמו אני לא כותב לו unit testing אני כותב לו integration testingation testing זה אומר שהunit of work שלי כולל את הדatabס [\[32:21\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1941s) כולל את הדatab בגלל שאני רוצה לראות שלא רק שאני יכול שזה קורה לו עם הSQLים הנכונים גם לבדוק שמשהו נקרא עם הSQLים הנכונים או עם הQU הנכונים זה גם זה חתיכת mainity CRP אבל אם אני רוצה אבל אם אני באמת רוצה לבדוק את זה אני אני עושה דביס לטestינג ואני בודק כשהמבנה של הדטביס תומך בהכל שאני יכול לעשות אינסרטים ואפדייטים וכל הדברים האלה עכשיו במקרה של clוד אני לא בטוח אני צריך להסתכל על הכל כי cלא זה הכי דפארטי שיכול להיות אתה לא יכול באמת ליצור קלאוד פרטים משלך לוקחלי אצלך שרץ רק אצלך למחשב אתה טועה >> כן >> כן אני טועה או כן אתה יכול >> כן אתה טועה יש סימולציה של קלאד אצלך [\[33:05\]](https://www.youtube.com/watch?v=gtRXDuLj8uc&t=1985s) >> אם זה סימולציה זה לא קלא דבר ## Related - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1) · The Art of Unit Testing, 2nd ed., ch. 1 Builds the definition of a unit test step by step in C#, the same definition this lesson starts from. - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) · osherove.com Explains a unit as a unit of work from entry point to exit points: return value, state change or third-party call, as here. - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19) · The Art of Unit Testing, 3rd ed., ch. 1 Book section on exit point types, the three kinds of end results the lesson uses to define a unit of work. - [Unit Testing decoupled from TDD as well== Adoption](https://osherove.com/blog/2008/10/1/unit-testing-decoupled-from-tdd-as-well-adoption.html) · osherove.com Argues for treating unit testing separately from TDD, the same split between how and when to write tests made here. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [Tests that don’t assert anything](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7), ch. 7 - [Maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8), ch. 8 #### The Art of Unit Testing, 2nd ed. - [Testing results that are system state changes instead of return values](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec7), ch. 2 - [First steps with NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3), ch. 2 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6), ch. 1 - [Interaction testing using mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4), ch. 4 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 #### osherove.com - [Naming standards for unit tests](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html) - [Refactoring String Calculator with SOLID Principles in Mind - Examples Needed](https://osherove.com/blog/2013/3/6/refactoring-string-calculator-with-solid-principles-in-mind.html) #### artofunittesting.com - [Definition of a Unit Test](https://www.artofunittesting.com/definition-of-a-unit-test) [Next lesson Syntax](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/syntax/) --- title: "Syntax" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/syntax.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/syntax/" tags: [] author: "Roy Osherove" description: "Lesson 2 of 22 in TDD in .NET in Hebrew (Day1 - Unit Testing and TDD 101), 29:43. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Syntax 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day1 - Unit Testing and TDD 101 Lesson 2 of 22 Duration: 29:43 [Watch on YouTube](https://www.youtube.com/watch?v=q-niFxJT2hE) Spoken in Hebrew ## In this lesson Roy Osherove argues that [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") and [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)") complement each other, then introduces the [xUnit family](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)") of frameworks, from SUnit through JUnit to [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)"), which the course uses, and its competitor MSTest. He explains the [arrange, act and assert](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "The Arrange-Act-Assert pattern (The Art of Unit Testing, 3rd ed., ch. 2)") parts of a test, the [TestFixture and Test attributes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6 "More NUnit attributes (The Art of Unit Testing, 2nd ed., ch. 2)") the runner finds through reflection, a [three-part test name](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html "Naming standards for unit tests (osherove.com)") separated by underscores, putting the expected value before the actual one, and [one logical assert per test](https://osherove.com/blog/2005/4/14/try-to-avoid-multiple-asserts-in-a-single-unit-test.html "Try to avoid multiple asserts in a single unit test (osherove.com)"). He starts a calculator class library in Visual Studio with ReSharper, adds a separate test project and installs NUnit with NuGet. ## Transcript 4,411 words [\[00:03\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=3s) בדיוק הייתי עושה ממש מירור של הקלאוד שיש לי שליטה עליו שאין בו דטה בכלל או שיש בו את הדטה הבסיסי והמינימלי והייתי בודק ממש באנטגרש test שלוקח להם הרבה זמן ובשביל זה יש לי את הניט ממש ככה יש דברים שאין ברירה חי להם test האנטגרשט test זה בסוף סוף מה שאומר לך שהאפליקציה שלך עובדת זה שיש לך מלא יestטים בסופו של דבר לא אומר לך שום דבר אם האפליקציה עובדת רק אומר שנראה לך שהאפליקציה או שהקוד בדעת אותו נכון אז זה תמיד שילו של [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1 "Defining unit testing, step by step (The Art of Unit Testing, 2nd ed., ch. 1)") testing הם לא מחליפים אחד את הש אם תעשו רק testing תצטרכו לחכות שהאפליקציה שלכם תהיו מוכנה עד שתתחילו לעשות פה והרבה פעמים אתם מתחילים לעבוד על פיצ'ר ורק עוד שלושה חודשים הוא יהיה מוכן [\[00:43\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=43s) אוקיי אז השילוב הוIT testing אתם יכולים לעשות דבר עכשיו גרation testing אתם יכולים להוסיף אחר כך unit testingים הרבה יותר מהירים אז אפשר לקבל פידבק הרבה יותר מהיר ששברת משהו גרשן test אתה מקבל פידבק הרבה יותר איתי אבל אבל אתה גם בודק הרבה יותר דברים באותו זמן זה תמיד שילוב ששני שני הדברים האלה חברה שיש להם שיש לה רק סוג אחד בדרך כלל חברה שחסר לה משהו או חסר להגהירות פיתוח כי נורא מפחיד לקבל פידבק או אתה עושה משהו וא רק אחרי יומיים מקבל פידבק אם שברת משהו [\[01:14\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=74s) או שאין להינטגרש test ואז הרבה פעמים מגלים בפרוד של המון בעיות שאפשר היה לגלות הרבה יותר מומר אז אם יש לכם server אין שום בעיה שגם יהיה לכם testing server כן קצת מגיע מה שאמרתי קודם על בדיקה שלספ אבל בעיקרון הבדיקות הטסטים בכלל הם הם בודקים בעצם סוג של בקורפילי נכון שלי בקוד שלי ואני רוצה לראות האם כל הטestטים עובדים >> כן >> אבל זה לא נותן לי אפשרות לבדוק מצב הפוך שנגיד המספה של המרכת שורץ על כמה שרטים וכל דפל אמת מריץ חלק חלק אחד מהתת מערכת שלנו אז חלק מהבדיקה צריך להיות גם פורד פטבity כי לראות שהבדיקה שהפולנת [\[01:50\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=110s) החדשה עובדת גם עם חלקים אחרים שלא עברו את המיגרשן הזה זה יכול להות דקה נוספת מעניינת אינטגרש test נוסף שהייתי מוסיף אבל הוא לא הוא לא משהו שאולי רץ בנילי ביד אלא רץ לפני שאתה עושה deפמ זה את >> זה מה שהטest שלנו בעצם לא בודקים את זה כי עושה מהגרש test אם אתה רוצה לבדוק אתה מה שלך לסביבה סביבה by definition third party זה משהו שאין לך שליטה עליו אם זה רץ בקלאד אין לך שליטה על זה אתה חייב test אז אתה אומר אני מרים איסance ואני בודק מה קורה אני יכול להריס המוןגרש test על אפליקציה עכשיו דרך אגב זה יכול להיות מעניין אין שום מניעה ש שאתם תריצו גם את הוITטestים בקלאוד אם הקלאוד איך שהוא משנה את ההתנהגות של הקוד למרות שלא נראה לי [\[02:33\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=153s) כי אני יודע שיש סביבות ש בדיבד אתה עושה דבר אחד אבל בפודקשן או ברליס אז אתה גם עושה אופוסקציה וכולי הופוסקציה זה שינוי שינוי הקוד וגם עושה משנה אופטימיזציות למיניהם אז אתה רוצה להריץ גם בדיבג וגם ברליס אבל אני לא יודע אם הקוד שלכם שאתם מעלים אותו להזו הוא גם עובר איזשהו תהליך כזה לא בדעתי אני מניח שלא עבר אז אם זה אותו קוד אז תים test צריך לרצנן ונטגרש test כן הייתי מוסיף כמה שיותר test ברגע שאני יודע איך הייתי מוסיף אותם אבל צריך לוודא שהם [\[03:07\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=187s) וזאת הבעיה הכי גדולה של clודף זה שוקח המון זמן לעשות פלוי גם ולבדוק שהטest שכתבת באמת יכול לרוץ אטגרש >> אבל זה באמת נושא קצת זה נושא שצריך לשבת ממש עם אנשים ולנסות לפתור אותו כי כל חברה זה סביבה אחרת לגמרי האינטגרשט test נכתב באותה תשתית כאילו זה עודסט של unit testing >> תחשוב על integrגרation test כטest שנכתב באותה תשתית נגיד במקרה שלנו זה יהיה [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)") כי כל הקפורס הזה נעשה ב-NUnit ואבל גם יכול להיות בMS הוא פשוט מפעיל אפליקציות אבל הוא לא עושה [פייק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") לשום דבר הוא פשוט מפעיל את הAPI ומצפה שהכל יעבוד הוא כביכול UI שרץ [\[03:45\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=225s) וקורה לhtר אוקיי. אז אם אנחנו רוצים לכתוב את הטestטים בצורה ש שהיא מקלה עלינו לכתוב את הטestטים בצורה שיהיה repatable ובצורה פשוטה אז יש המון המון פרwורקים לדבר הזה. עכשיו test frameworks בגדול נקראים x unit framewor או unit test framewor נקראים x unit frameworks הרמ שהx זה שם של שכר כלשהי ואז אומרים unit [\[04:23\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=263s) אז הראשון היה בכלל בסמלט ונקרא SUnit אחרי זה יש [JUnit](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39 "The xUnit frameworks (The Art of Unit Testing, 3rd ed., ch. 2)") CppUnit ו-VBUnit זה הפרוק שאני התחלתי איתו עכשיו NUnit שזה הפרוק שאנחנו נתחיל איתו זה הפרימוק שהיום הכי הרבה משתמשים בו למרות שמסטest הוא באמת המתחרה הגדול שלו אבל יש ביניהם הבדלים תאומיים מבחינת החשיבה ומבחינת היכולות את JUnit זה ה זה המקור שממנו הIT testing בדיוק. זאת אומרת לפני שהיה MSTest היה NUnit ו היה של JUnit [\[04:56\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=296s) ובתור פורט של J הוא גם לקח כמה מהקונבנציות שהיו בג'אבה באותו זמן ולכן חלק מהשמות שאתם תראו הם נשמעים בהתחלה נורא מוזרים. MSS דווקא שיפר חלק מהשפה הזאת ועשה את השמות קצת יותר קלים וקריים. היום יש פריורק לunitesting בגדול לכל שפה שקיימת רובם הם open source free. אז אם אנחנו מדברים על גאבסקריפט unit testing וtdd אתם יכולים לעשות גם את זה מדברים על flashש אז גם בזה אפשר אני אפילו ראיתי [\[05:26\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=326s) Unitest frameworks לדברים כמו hot מישהו מכיר את אוטו יפה אז אני אפשר לחתוב בזה unitest למי שלא יודע שזה פרימו בכלל לאוטומציה של המחשב לוקלית אתה עושה מקרואים זאת אומרת כשאני לוחץ f3 אז תפעיל את הנטפד ותשים בו את הטקסט הזה כל מיני דברים מוזרים אז אפשר לכתוב ביזה טסים לסקריפטים הזה אני בעיקר בעבודה שלי התעסקתי עם עם JUnit, NUnit, VBUnit ו-CppUnit. זאת אומרת אני בא מהרבע שפות האלה אבל בשנים האחרונות אני גם עבדתי ברובי שנתיים וגם בדוטנט ב-10 שנים האחרונות או עד שזה התחיל לדבר [\[06:03\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=363s) אבל מה שיפה זה שברגע שכתבת טestטים באחד מהפרימוקים האלה יחסית זה מאוד קל לכתוב טסטים בפרימו אחרים ולינתן שאתה יודע את השפה לכתוב את הטestטים זה לא האיש בגדול להבין את הפרימוק זה משהו שאפשר להבין ב-10 דקות שעה כל הפרימוקים מאפשרים שלושה דברים לכתוב את הטestטים, להריץ אותם ולראות את את הבעיות אם יש. זאת אומרת אקטיבה היא בצורה אפורמיסטית [\[06:33\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=393s) בדרך כלל די סטנדרט. יש קלאסים ובתוכם יש טestטים או שיש להם אטרביוטים יסיים או משהו שני naming convention ש מסמן שהם testים. ההרצה שלהם יש גם commנדלי line וגם UI וכשמריצים אותם ויש תוצאות אז רואים מה נכשל ובאיזה שורה זה נכשל את את הxpectד results זוכרים הרבה דברים by deffaultט אבל זה אינפסטקר מאוד קל ומאוד פשוט בכל test יש לנו שלושה חלקים כמו כל דבר בצבא arrange up והסט [\[07:05\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=425s) ובunit אנחנו נכתוב test בתוך קס שנקרא test fixurms test זה נקרא ‏test classס שזה שם הרבה יותר טוב תחשבו על פיקure כcס תחשבו על זה כמדף כלשהו testure זה אריבוט שהוא חלק מ-NUnit שמוסיפים referלס ל-NUnit מקבלים את האatבט הזה ועוד כמה מכיוון שכל הטסטים שלנו הם בעצם פונקציות הם חייבים להיות בתוך קלאס לא משנה מה השם של הקלאס אני בדרך כלל מתחיל בשם שנגמר שמתחיל בפרויקט שאני בודק [\[07:37\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=457s) אם זה הקלאס היחיד אם זה הפרויקט אני מתחיל בשם של הפרויקט ואם זה אם אני בודק קלאס אז אני כותב את השם של הקס שאני בודק. אם הUNIT work שלי הוא יצול מקס אני כותב את הUNIT לדוגמה לoging אבל הרבה פעמים ו90% מהזמן זה ברמת הקלאס כי שם נמצא הפאבליק מוד שלי איפשהו ובדרך כלל הוא גם שם נגמר ואז את המילה test אבל אני לא חייב לתוך את המט פשוט עוזר לי מבחינת הקonveng [\[08:08\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=488s) כל הטestטים יכולים להיכתב בפונקציה שלא משנה מה השם שלה עיקר שהיא פאבליק ולא מקבלת פרמטרים ולמעלה חייבים לשים את האטריביוט של test האטריביוטים האלה עוזרים לtest runner שלנו לcand ולi שמקבלים assembly או dl compile ומסתכלים בפלקlection ומחפשים את האatיוutים מי יודע מה זה reflectiontion אוקיי הם משתמשים בפלקש כדי להסתכל על האטריביוטים וכל האטריביוט שיש לו testם פשוט עושים לו עכשיו זה שם מאוד גרוע לטסט בסדר עכשיו זה ככה בן אדם שבא מגוניט היה כותב טestטים היום כי ביוניט כל test חייב להתחיל במילה ‏test כי הnaming convention לgit בזמנו לא היה אטריוטים היום בג'אבה כבר יש אבל פעם לא היה אטריביוטים [\[08:50\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=530s) ולכן ה הרנר חיפש את כל הפונקציות שמתחילות במילה test היום אנחנו לא צריכים את זה יש לנו את הדבר הזה don't prepat המילה גם לא מספיק לבט testים בדרך כלל אנחנו ניתן להם איזשהו סוג של nameing convention זה nameing convention שאני מאוד ממליץ עליו בתור התחלה מכיוון שהוא מכיל שלושה חלקים שעוזרים לנו מאוד להבין מה היה אמור לקרות ומה מה הדבר שאני בודק בכלל. אז זה דוגמה של ט בצורה שבה אני הייתי כותב אותה ויש פה הרבה דברים יש פה הרבה הרבה לוגיקה כן איך הוא כתוב [\[09:27\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=567s) דווקא נתחיל מה מהבפנים ואז אני אסביר מה קורה בחוץ הטest מורכב משלושה חלקים arrange וסט arrange זה חלק שבו אני אוסף את האובייקטים שלהם אני אבדוק משהו נקנק את המערכת לפני שאני בודק אותה לפעמים זה שורה אחת לפעמים זה יכול להיות גם 15 שורות תלוי כמה מסובפת המערכת ואיך הדיזיין נראה האקט הוא בדרך כלל שורה אחת. לפעמים הייתי יכול להיות יותר משורה אחת אבל הרבה פעמים זה שורה אחת שזה של איזשהי פונקציה שהיא פאבליק לפעמים זה עם פרמטר לפעמים זה בלי לפעמים היא מחזירה resultלט לפעמים היא לא מחזירה resלט היא משנה סטייט [\[10:01\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=601s) לפעמים היא לא מחזירה resלט אבל אז העסרט שלי נראה אחרת אני בודק שמשהו נקרא פה אני מקבל resultלט אז אני משתמש בקלאס שנראה נקרא אסרט כמעט בכל הפריימורקים יש או קלאס שנקרא אסט או שיש פשוט מאות פונקציות שמתחילות במילה אסרט וj זה מאות פונקציות אחד בסרט לאסרט יש המון המון statics. As rquונקציה שתשתמשו ברוב הסיכויים הכי הרבה ואתם בודקים שה expectected value [\[10:34\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=634s) Equals the actual. זאת אומרת זה תמיד מתחיל בexpected ואחרי זה זה actual. הרבה פעמ אנשים פה ותבים את זה הפוך. זה נורא מבלבל בהתחלה. אם תכתבו את זה הפוך הארורים שתקבלו עם הטest הזה יקשל יהיו מאוד מבלבלים ציפיתי להקט resultל אבל קיבלתי את הפקט כאילו כל מיני דברים כאלה כן אם נגיד שקיבלתם ארבע הוא יגיד לכם אם הטסט הזה יקשל מה שיקרה זה שתקבלו אפtion ואז יכתב לקסולנלי line או שבui אתם תראו באדום [\[11:05\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=665s) הטest נכשל ציפיתי לארבע אבל היה שלוש אם כתבתם את זה הפוך מה שאמור להיות זה ציפיתי לשלוש אבל היה ארבע אז הסדר מאוד משנה מבחינת ההבנה של איך למה הטסט נחשב בכל הפריורקים האלה בכל ביוני תמיד יש עוד פרמטר אחד שלישי בסרט הפרמטר הזה הואסטרינ מage ומה שהוא מתכוון זה המסג שאתה רוצה לכתוב אם האסרט הזה נחשל הרבה פעמים אנחנו רוצים לכתוב את המסג' הזה בגלל שהשם של הטסט לא מספיק טוב אז הסיבה היחידה שיש לי לכתוב את המסג' הזה זה עם השם של הטסט לא מספיק טוב. [\[11:42\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=702s) אני מעדיף לא לכתוב אותו כי מה שאני ראיתי הרבה אנשים עושים זה הם כותבים את המסג' ואין להם כוח לכתוב את המסג שהם לא מבינים למה מה אמור להיות שם ואז הם כותבים משהו שכבר הפרמורק נותן לך או שהם סתם נותנים איזשהו איזשהו אקסטר סטרינג שמאוד קשה להבין בדרך כלל זה לא שווה שום דבר האקסטר פרמטר הזה הוא רק מבלבל יותר אז במקום זה מה שאני עושה זה שאני ממש ממש ממש מקפיד על השם של הט [\[12:16\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=736s) אז השם של הטestט מורכב משלושה חלקים הדבר הראשון זה הIT of work במקרה הזה אם זה רק פונקציה אז זה השם של הפונקציה אם זה קלאס יכול להיות שזה השם של הקלאס זה מאוד משתנה בדרך כלל זה מתחיל בשם של הפאבליק פנקש שאני גוד הדבר השני שימו לב שיש פה את האנדרסקורore הזה זה מאוד חשוב לרדity בטestטים שיש את ההבדל הזה כשאין את האנדרסקור מאוד קשה להבין צריך ממש לקרוא ב ממש קשה לקרוא add two numbers זה בעצם הסנר אוקיי [\[12:47\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=767s) כאשר אני קורא לד עם numers אז צריך לקרות את הדבר הזה שבו על זה כמו משפט אז זה הexpected behavior או expected result או expected to third part שור זה ככה אז עוד פעם add two numbers su them up בדרך כלל שלושת החלקים בדרך כלל אנשים שקוראים testingים הם שוכחים לפחות אחד מהם או שלא הם לא חושבים על אחד מהם אז הרבה פעמים אנחנו רואים ואז תחשבו על הבן אדם שצריך לקרוא את הטest שלכם עוד חמש שנים כמה הזמן הטestטים שלכם אמורים להחזיק חמש 10 שנים יחד עם כל הקוד של האפליקציה עוד חמש שנים בן אדם יקרא את הטסט שלכם גם עוד חצי שנה אתם תקראו את הטסט שלכם ולא תזכרו שאתם כתבתם אותו תגידו add sד [\[13:33\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=813s) אוקיי אבל מתי אני רואה פה שלושה טסטים כאלה ואז תצטרכו לקרוא את הקוד של הטסט והמטרה של השמות של הטestטים זה שאם תסתכלו על השם לא תצטרכו לקרוא את הקוד של הטestט אוקיי המטרה שלי בשם הזה זה שלא תצטרכו לקרוא את הקוד כי אם אתם צריכים לקרוא את הקוד אתם צריכים לראות את הסורס קוד שלי כשטestטים רצים והם נכשלים הרבה פעמים כל מה שיש לי זה את השם של הטestט אין לי את הקומנטים מעל הטest אין לי את הקוד של הטest עצמי אני צריך לעשות דאבל כדי לראות אותו ולכן [\[14:04\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=844s) אם אני אם אני רואה עכשיו יש לי 1000 טestטים ו15 נכשלבים ואני רק יכול לראות את השמות ולהבין מה מה קורה. אני לא צריך להסתכל אפילו על הקוד של הטestטים. הרבה יותר קל. הרבה זה חוסך לי המון זמן. עכשיו עוד דבר חשוב תשימו לב שבין הרange up והסרט אני שם ספייסים. יש לי לפחות שורה אחת ריקה ביניהם וגם קשור לרדity. הרבה פעמים אנשים כותבים את כולם בבת אחת אבל אני צריך לראות לפחות שלושה חלקים מרווחים ביניהם בטest. [\[14:35\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=875s) ואז הרבה פעמים אני בחיים שלא ראיתי את הטest הזה אני דווקא מתחיל מלמטה אני אומר אוקיי זה הסרט שלי איך קיבל מה מה מה הפעלת כדי לראות את זה אני אסתכל בדיוק אחד למעלה אוקיי ואז כל מה שמעל זה זה הרange אם אני מחלק את זה ככה אז זה הרבה יותר קל לקרוא ולהבין את הטestטים שלי אם בחיים שלי לא ראיתי אותם ואם כן ראיתי אותם עדיין חשוב לי הספייסים קנים אני לא צריך לחפש איפה האקט שלי לפעמים הרange יכול להיות מורכב גם מקיות לפונקציות איזה מהם זה האפקס [\[15:09\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=909s) שאלות יש גם יש גם fltion אבל זה כרגע לא משנה אני לא מראה את זה מה שחשוב זה שהappi הזה תומך בכל מיני סוגים שלס זה שהוא שכולם צריכים להכיר אם אתם לא תכירו את הסרט הזה ולא תשתמשו בו אז אחרי זה הפלוט הסרטס ירגישו קצת יותר מסובכים לאנשים שבחיים שלהם לא עשו את כל פונקציה הטest כזאת יש סרט יכול להיות יותר מהסרט אחד אבל יש לי בעיה כשיש יותר מסרט אחד. בוא נניח שיש לי פה שלושה הסרטים. [\[15:41\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=941s) כשהסרט הראשון נכשל מה שקורה זה שנזרק אקפשן וזה אומר שכל הסרט מתחתיו לא ירוץ. אז אני לא אדע מה קורה איתם. אז בדרך כלל מה שאני אומר זה שלא כדאי לכתוב יותר מאסרט אחד אלא אם כן כל האסרטים הם על אותו אובייקט. כי אם הם על אותו אובייקט אז אחד נכשל אז זה כבר לא בדרך כלל הכל כבר נכשל. אבל אם זה על אובייקטים אחרים והראשון נכשל עדיין אכפת לך מה קורה עם האובייקטים האחרים אז בדרך כלל אני מפריד את זה שיש יש איזשהו סוג של one concept your test אתה בודק דבר אחד logי דבר אחד לוגogי בדרך כלל זה עליי אחד אז אם יש לך person אתה תבדוק את הname ואת הage אני יכול לכתוב את זה באותוטest אבל אם יש לי person ש אז כל אחד מהם הוא resultלט אחר אני אבדוק כל אחד בטסט אחר ואז אם טסט אחד נחשב אני עדיין רואה את התוצאה של טestט אחר [\[16:30\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=990s) עוד שאלות? אז רגעז ברמה פרקטית אם יש לי פיסת קוד שאני רוצה לבדוק שמשפיעה באמת על שני דברים לא על פס יש לך שני resultלטס >> שני resultטס אבל זה בדיוק אתה פיסת קוד אתה ממליץ פשוט לשכפל את הטest פעמיים ופעם אחת לבדוק את >> תכף נדבר על מטability אבל קודם כל לשכפל את הטest ואחרי זה לעשות refctורing שהוא יהיהable אבל התשובה היא כן בהחלט כל אחד מהם צריך להיות בטest נכתב משלו כי גם האctטed behav שלך יהיה שונה שם נכון אני מצפה שהוא גם יכתוב ללוג וגם ישמור לדataס זה שני resultלס זה זה הIT of שיש לו שני resultלs זה בעצם שני unit of war כי כל אחד מהפיצ'רים יכול לעבוד בנפרד מאחר אתה יכול לעשות את זה אינטרמנטלי אני קודם כל גורם לפיצ'ר הזה לעבוד הנה זה עובד עכשיו אני גורם לזה לעובד בtd העבודה היא מאוד אינטרמנטלית אתה יכול לקחת כל דבר ולחלק אותו למטפלס feג'רס וזה אחד הדברים היפים בטd שכל הזמן יש לך משהו שעובד אפילו אם זה עובד ב-30% זה עובד אתה יכול לראות את הטestי הזה אתה יכול להביא משהו שהוא פרשה ששכרה עובד ועושה משהו [\[17:31\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1051s) אז שני resultלט זה שני test. עוד שאלות מבחינת מטלבity הצס הזה הוא לא משהו שימו לב אני עושה פה ישירות ניו לקלator בדרך כלל בטסט הבא שלי אם ברגע שאני עושה טest חדש ואני רואה פה שני ניו אחרי שהשני טestטים שלי עוברים אז אני עושה להם ריפקטורים עכשיו למה אני מחכה עם הריפקטורing למה אני לא עושה פאקטורing לדעתכם למה לא כבר מראש יכולים לעשות פה איזה פאקטורים או איזה setup מתוד למי שמכיר [\[18:12\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1092s) למה אולי יש צרכים שונים יש צרכים שונים לא משהו >> אולי לא ליצור תלות מראש זה יכול ליצור תלוט דווקא עכשיו יש הרבה יותר תלוות ברגע שאני עושה ריפקטורים ולכל הניים אז אני מוריד את התלות אני יכול לשנות את הכל במקום אחד >> אולי לא קרה לי קלקלת עוד פעם כאילו למה >> אולי אני אקרא לי אולי אולי אני לא אצטרך את זה עוד פעם אחלה אוקיי >> לא האמת שבמקרה של ניו זה בעצם אתה ישר מאתחל אותו בעקר הזה אבל אם היית נגיד עושה גם עוד דברים שמשנים את הקלקטור כדי להתאים אותו לטestט הזה אז >> אם היית שזה בטd אתה אומר >> לדוגמה כן אז אז בעצם כל כל מבחן היה אם היה לך נגידסטאפט מטד שעושה אז הוא היה צריך להתאים לכל המבחנים [\[18:54\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1134s) בהגדרה >> כל שורות נכונות אבל יש סיבה הרבה יותר פשוטה סיבה הרבה יותר פשוטה [test driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") בTD המטרה היא לצ ליצור פונקציונליות חדשה. המטרה היא לא ליצור טestטים. טestטים הם לא העיקר. טestטים הם גורם מזרז. המטרה בTD היא לא לבדוק שהכל עובד. שבtd אתה לא תבדוק שהכל עובד. בTD אתה הרבה פעמים תבדוק את ההפ. אתה תבדוק שהפיצ'ר מסוים עובד ואז תכתוב לו אולי מלא רנט testים את כל ה מה קורה עם זה מינוסים ומה קורה עם זה נלים. אבל קודם כל תבדוק שהפיצ'ר עובד. תגרום לו לעבוד כדי שתוכל לשחרר אותו, כדי שתוכל לקבל פידבק שאתה בכלל בכיוון הנכון. [\[19:29\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1169s) אם אני עכשיו מבזבז זמן על ריפקטורים של הדבר הזה, אוקיי, במקום ללכת להראות את הפיצ'ר הזה למישהו, אז מבחינתי אני אז אני פשוט מבזבז זמן. המטרה היא לא לעשות רפאקטורים אם אני לא חייב, לעשות רפאקטורים רק שאני באמת חייב, כשיש לי כבר שני טestטים שעוברים. אוקיי? אז מבחינתי טestט אחד זה כבר פונקציונליות כשהוא עובר. אם אני לא אם אה כשאני אכתוב טestט הבא ויוכח בבירור שיש פה שני דברים שחוזרים אחד על השני, אז קודם כל שהטestט השני יעבור. קודם כל שתהיה לי עוד פונקציוניות במערכת אחרי זה נשפר את הטסטים אוקיי הדגש הוא על הפונקציונליות במערכת שאני יכול לעשות דליברy [\[20:07\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1207s) אוקיי עכשיו בtd הרבה פעמים אני אכתוב testט ואולי קלטור אפילו לא יהיה קיים כי אני כותב את הטסט לפני שהקליוטור קיים אז אני יכול להחליט איך הפי נראה אז הטestט הראשון אפילו לא יתקמפל ואז אני אגרום לו להתקמפל אבל אני לא אתחיל לגרום לו להתקמפל עד שאני לא אסיים את כל הטestט יכול להיות שיש לי פה אפילו שלוש שורות שלא להתקפל אני אכתוב את הקוד כמו שאני אני מאמין שהוא צריך להתיגל כאילו הAPI המושלם כבר קיים בטסט הבא אני כבר עושה את הרפקטורינג אחרי שיש לי שניים שעוברים בגדול זה די גדול דומה למה שאמרת אבל הרבה אנשים כשהם עושים TDD הם כותבים את הקוד הזה ואז הם גורים לו להתקמפל ואז כותבים את השורה הזאת ואז גורים לו להתקמפל והרבה פעמים אתה יודע שפספסת משהו פה רק שתגיע לפה ולכן קודים את כל הטestו [\[20:51\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1251s) הכל כבר קיים עוד שאלות טוב אז אז בוא נראה לכם תמו אני ממליץ גם שיהיה לכם דברים לכתוב כי אני הולך גם לעבור על הרבה שורטקאטים ועל הרבה דברים שאני אבקש ממכם לעשות בסביבה שלכם אוקיי [\[21:22\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1282s) אז אם אתם רוצים עכשיו זה הזמן הטוב להביא שורט הזה להביא אולים לכתוב טוב אני מורים פה עם 2010 נכון >> אוקיי כשאני מתחיל לכתוב טestטים אני הולך אני הולך להוסיף פה בעצם שני פרויקטים פרויקט אחד הולך להיות הפרדקש קוד שלי בדרך כלל אני מתחיל מכיוון שאנחנו עדיין לא מדברים על TDD אז אנחנו נתחיל דווקא מאיזשהו [\[21:53\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1313s) C#brary אוקיי ונקרא לו אקulator הכי פשוט שבר נכון שכולם צריכים לקרוא צריך להכנס לכם רואים מעולה אחורה אומר גם שומעים מעולה מהחורה >> פתו כיסא בשורה הראשונה רמי בשבילך כתוב עליו רמי אוקי כתוב לברי [\[22:26\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1346s) מהקלקו פרודקט אוקיי אמין עכשיו מה שאני אעשה זה אני אני בכוונה אכתוב פה איזשהו אה אני אשנה את השם של הקלאס הזה כדי שיהיה לנו איזשהו משהו לבדוק אני לא הולך לעשות פה איזה משהו מיוחד אתם אצלכם גם תיקחו את זה חצי שנייה ותעשו את זה עכשיו אני משתמש אצלי ברישרפר ואם אתם רוצים להשתמש בשורט שני אני משתמש אני אלך למני של options [\[22:58\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1378s) ופה בזו Studio integraation אוקיי יש לי את הפונקציה הזאת אוקיי אני משתמש בגרסה של 2x בגלל שאני משמשתמש ישן שלהם אז אני רגיל לשורים הישנים אצלכם בדפולט זה יהיה סטודיו אם אתם הקטדתם או שלא יהיה לכם בכלל אז אם יהיה לכם שום שורטים שעובדים ברשרטר זה מה שאתם צריכים לעשות ללכת לסמן את זה ולעשות אפלי עכשיו היו הרבה שאלות ביום חמישי למה זהזל משתמש בריש ואז לאט לאט אתם תראו חלק מהסיבות אחת הסיבות הכי מעצבות אחת הדברים שהכי מעצבנים אותי עדיין ב-Visual Studio בלי רשפר זה שאם אני עושה rename לקס הוא לא עושה rename לפייל אלא כי אני עושה את זה בפס פה אז פה מה אבל רק אם עושים רני לפי עכשיו אני צריך לפתוח את הפייל [\[23:46\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1426s) מה יותר פרודקטיביצד ימין >> צד ימין לכת לעשות כלי צריך להשתמש בעכבר בשביל זה מה הבעיה קלטור F2 דרך אגב זה הקלאס שלי אני רואה פה מלא זים שאני לא משתמש אז נסיעה על 10 אני אתטר מהם קוד נקי public in add בכ בכוונה נעשה פה איזשהי פונקציה הכי פשוטה שבעולם in x in y contנטרול shiיפ כדי לסיים את השורה ולהתחיל את החיים שלי אני x וx [\[24:22\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1462s) אתם רואים פרוגמים עובד אוקיי ואני פה שיפט כדי לסיים את השורה פשוט חכם אני כי אני יודע רק מה צריך לעשות לעשות לעזור לקפיילר אבל אני בכוונה אוסיף פה קצת לוגיקה כי פונקציה כזאת זה לא פונקציה שהייתי כותב לה unit testing network כי זה אין פה לוגיקה יש פה מתמטיקה מתמטיקה וואלה הייתי עושה פה עכשיו מיליוני טestטים שבודקים את כל הרנ של המספרים הייתי עושה פה לולאות וכולי אבל ביוני testים אני בדרך כלל לא עושה לולאות אני רוצה שהטסטים שלו כמה שיותר פשוטים אז בדרך כלל אני אכתוב אותם רק לדברים עם לוגיקה אז בוא נוסיף פה לוגיקה if x קטן מאפס [\[25:07\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1507s) אז ריטר מינוס1 זאת אומרת אתה רק עובד עם מספרים שהם חיוביים אוקיי קטן מאחד בוא נניח זה ב אמ אוקיי אז עכשיו אם אני רוצה לכתוב טestטים לדבר הזה ויש לי קוד קיים אני בכוונה מוסיף פה פרויקט חדש של טestטים אני לא מוציא את הטestטים באותו פרויקט אני בדרך כלל אוהב להפריד ביניהם למרות שיש מקומות שאוהבים לשים את הטestטים כחלק מהפרויקט זה חשוב אם אתם רוצים לעשות דפל לטסטים שלכם וגם להריץ אותם בפרודקשן זה דרך אגב זה לא בהכרח דבר רע אבל גם שם אני פשוט עושה דפל גם לdl של הטesting בפודקש מה אכפת ללקוח שלי אני פשוט יכול הלקוח אומר לי משהו לא עובד לי אז אני יכול להריס את testive או ברמור או באיזשהיא צורה [\[25:56\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1556s) אוקיי אז מה שאני עושה זה אני בכוונה עושה clסליבר אם הייתי כותב פרויקט של MSTest הייתי עושה פה test אבל אנחנו משתמשים פה בג עכשיו יש כמה סיבות להשתמש בני א' הטestטים רצים הרבה יותר מהר וב יש הרבה יכולות בוניט שאין ב-MSTest יש לפחות שתיים מאוד חשובות אנחנו נעבור עליהם עוד מעט והדבר השלישי זה שitate הוא extensible אם אנחנו רוצים להוסיף לו פיצרים מאוד קל לסט זה כמעט בלתי אפשרי להוסיף פיצ'רים [\[26:28\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1588s) עכשיו מה השם של הפרויקט שלי אופס אוקיי מה השם של הפרויקט צריך להיות בדרך כלל זה השם של הפרקט זה השם של הproקט אז אם שזה byור ‏prodctט אז זה יהיה my calculator product unit tests אוקיי זה נראה ככה [\[27:13\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1633s) אוקיי אמ עכשיו הaming convension הזה זה חשוב כי כשאני עושה רוי כשאני מסתכל על טestטים של מישהו אחר הרבה פעמים אני נורא אני רוצה שיהיה לי קל למצוא את הטestטים של פרויקט או של קלאס מסוים אזמנ אומר שזה עוזר לי כי בדרך כלל הם יהיו אחד מתחת לשני אבל יש חברות שאוהבות להסיב את הקונבנשן של הטestטים תמיד בהתחלה ואז כל הפרויקטים של הטestטים הם גרופ לפי ה הפרפיקס שלהם החלטה שלכם כל זמן שאתם קונסיסטנטים זה מה שחשוב זאת אומרת אם יש לכם גם כזה וגם כזה אז פתאום זה נהיה הרבה יותר מסובך למצ שאתם קונסיסטנטים זה לא משנה. [\[27:48\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1668s) אוקיי, בואו ניפטר גם האלה, אני לא צריך אותם עד שאני לא באמת צריך אותם. השם של הקלאס הזה במקרה הזה שלי זה יהיה tests. עכשיו אני צריך את האatטים של NUnit, אבל אין לי פה n unit. אז מה שאני אעשה אני משתמש ב-NuGet כדי להתקין NUnit ולהוסיף את הרפרס אליו. למי שלא ישתמש בנוגט, מישהו השתמש בנוגט בעבר. מי יודע מה זה נוגט? אוקיי, [\[28:18\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1698s) יש כמה אנשים שלא יודעים, אז אני אסביר. NuGet זה extension ל-Visual שנורא מפשט את התהליך של להוסיף dependencies לפרויקט שלנו. אז אם היום אם פעם הייתי צריך ללכת לאתר של anu.com להוריד את הזigגפייל לעשות לו unz לקחת את dl לעשות לו reference מתוך הפרויקט שלי אז עכשיו אני יכול ללכת פשוט ללי package manager package manager consו שעובד בטח כפגין לתוך studio עם power shell [\[28:48\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1728s) יש לו גם UI אבל אני בדרך כלל כבר לא משתמש בUI כי הui הרבה יותר אני יכול פשוט לכתוב פה אני עושה טב פשוט כד להתחיל להמשיך פק ואז אני נותן פה שם של פק אם אני עושה nu ואני עושה tab עכשיו הוא מביא לי את כל הדברים שמתחילים בNU אתם רואים שיש לי NU city NU analize אם אתם לא רואים זה נראה ככה מה שאני צריך זה NUnit אז אני פשוט כותב NUnit אני לא צריך אני לא אני יודע את השם שלו אני עושה install package NUnit ומה שקורה עכשיו זה שהוא מוריד את הפקage מוריד את הזיפייל והוא מתקין אותו אבל לפויקט לא נכון בדפאולט זה הולך לגרות לכם כמו שזה קרה לי עכשיו כי אני תמיד שוכח את החלק הזה פה בקומבו בוקס אתם צריכים לבחור באיזה פרויקט זה אקטיב [\[29:35\]](https://www.youtube.com/watch?v=q-niFxJT2hE&t=1775s) אז אתם זוכרים הפרויקט אתם בוחרים את הפרויקט של הITסטים ופשוט חוזרים על הפעולה >> אנחנו רגע נצל את זה להפסקה קטנה นะ ## Related - [First steps with NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 2 First steps with NUnit, the framework the lesson installs and whose TestFixture and Test attributes it explains. - [The Arrange-Act-Assert pattern](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2) · The Art of Unit Testing, 3rd ed., ch. 2 Book section on the Arrange-Act-Assert pattern, the three test parts the lesson walks through. - [Naming standards for unit tests](https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html) · osherove.com Roy's three-part UnitOfWork\_StateUnderTest\_ExpectedBehavior naming, the underscore-separated test name shown in the lesson. - [Try to avoid multiple asserts in a single unit test](https://osherove.com/blog/2005/4/14/try-to-avoid-multiple-asserts-in-a-single-unit-test.html) · osherove.com Explains why to avoid multiple asserts in one test, backing the lesson's one-logical-assert rule. - [NUnit vs. MsTest: NUnit wins for Unit Testing.](https://osherove.com/blog/2010/3/5/nunit-vs-mstest-nunit-wins-for-unit-testing.html) · osherove.com Compares NUnit with MSTest, the two .NET frameworks the lesson contrasts. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [The xUnit frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2#sigil_toc_id_39), ch. 2 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 #### The Art of Unit Testing, 2nd ed. - [More NUnit attributes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6), ch. 2 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1), ch. 1 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 [Previous lesson Introduction](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/introduction/) [Next lesson Test Demo](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/test-demo/) --- title: "Test Demo" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/test-demo.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/test-demo/" tags: [] author: "Roy Osherove" description: "Lesson 3 of 22 in TDD in .NET in Hebrew (Day1 - Unit Testing and TDD 101), 34:54. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Test Demo 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day1 - Unit Testing and TDD 101 Lesson 3 of 22 Duration: 34:54 [Watch on YouTube](https://www.youtube.com/watch?v=80H_AvRX6oM) Spoken in Hebrew ## In this lesson Roy Osherove shows where NuGet comes from and writes the first calculator test with ReSharper, explaining why he picks plain inputs such as 1 and 2 over numbers like 1337 that make a reader wonder. He prefers the TestDriven.NET runner, maps a keyboard shortcut to rerun the last test action, and runs any method under the debugger without a test. He adds a test for negative numbers, keeps random values and logic out of [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)"), and replaces the [SetUp method](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162 "Avoid setup methods (The Art of Unit Testing, 3rd ed., ch. 8)") with a [factory method](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "Trying the factory method route (The Art of Unit Testing, 3rd ed., ch. 2)") so each test stays readable on its own. ## Transcript 4,949 words [\[00:07\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=7s) איך משיגים את הנוגט? הולכים ל tools extension manager הולכים לאנליין gallery זה אוטומטית הולך לה והראשון זה יהיה נוגט מתקינים אותו עושים restart Visual Studio וזהו יש את זה אוקיי עכשיו הוא בא הרעיון בא בכלל מעולם בעולם openסופי ובפייתון יש את הנושא של ג'מס שאתה מתקין דברים אתה עושה בעצם לאיזשהו ג'ם קיבלת רפרס ולפני בערך שנה וחצי הפרויקט הזה התחיל גם בעולם הטנט [\[00:41\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=41s) בעצם היו שני פרויקטים או שלושה אפילו אחד נקרא open map ואז מייקרוסופט החליטה CPA מאמץ את אחד מהם לחיקה והתחילה ככה לפתח את זה אבל הפרוד הזה היום הוא open source הוא hosted לדעתי ב ב-CodePlex למרות שיש הרבה לחץ להביר אותו לגיטה והיום אם אתם רוצים אתם מגלים היום בג בנוגט אתם אתם אשכרה יכולים לבוא ולהרגיש פץ ולנסות לתקן אותו להוסיף שפ זה די מדהיק [\[01:12\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=72s) אני אוריד פשוט את הרנס לin שיש לי בפרק כי אין צורך ואת הpages config הpages config זה בעצם מה שבסution explorer הדבר הזה שאומר איזה גרסה של הדpencies יש לך עכשיו מה שיפה זה שנוגט אני יכול גם להריץ אותו ברמת הבילד server שלי ולהגיד לו תביא את הpפendנenes אוטומט ואז אם הם לא פקס קנטרול ואז הוא יביא אותם לפי הגרסה שיש בקונפליק שזה די נחמד אבל זה לוקח קצת זמן אני אישית עדיין בעולם של [\[01:45\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=105s) לשים את את הפנenנס שלי באיזשהו binary dirקטורy ולשים אותה בחלק מהסורקול זה משתנים לפי הסורקנטרול וגם בזה זה תומך אפשר לשים את כל הבינary בעצם יש ספריה של הבינaries לוקלית בפרויקט שלכם שנוגט יוצר אתם פשוט מוסיפים אותורס אז זה היה בעצם בפוס הזה סיימתי להתקין את [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)") שזה בסך הכל nunit.framework.dll [\[02:18\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=138s) זה זה אמור להיות כל כך פשוט אני שמח שסוף סוף זה כזה פשוט אז אני אתחיל בלהוסיף testure אביו אז אני מתחיל פה במילה test אבל אין לי פה את הusing אז אני יכול להשתמש במה שקרה smart comptionarter שזה contrול ‏altספס וזה מביא לי את כל הדברים גם אם אין לי אליהם זאת אומרת אני עושה פה test fixure וזה מוסיף גם את בשבילי אז אני לא צריך לכתוב את השם המלא יש את זה בזלס אבל צריך לכתוב את השם המלא ולמי יש כוח שתי [\[02:51\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=171s) הדבר הבא test public void עכשיו מה השם של הטest שלי אז בואו ננסה לכתוב טס לדבר הזה יש למישהו רעיון מה הוא רוצה לבדוק פה? ‏add אוקי posive numers add two positive numbers ומה אתה רוצה שיקרה [\[03:30\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=210s) >> לא זה לפחות אני אומר שיש הקשרה זה לא רע >> שפט כדי להוסיף את השטויות האלה עכשיו רישרד בהתחלה צועק עלינו על הדבר הזה הנימי קונש שלנו הוא לא אוהב את זה אבל כולם יודעים שרש לא מבין שום דבר בחיים שלו אז אני עושה alt ואני אומר לו inspection options for ins consistent naming ואני אומר לו shut up עשה לי hint אוקיי אז arange אני יוצרקulatorulator עכשיו קלator הוא לא קיימ לי עדיין אין לי reference לפרויקט אזרפר אני לא צריך לקמפר רשרפר אומר לי זה לא יתקמפל לך [\[04:02\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=242s) אבל אם אתם רואים פה את המנורה הזאת כל פעם שיש לי את המנורה הזאת אני יכול לעשות alt enter הוא אומר לי היי אבל יש אחד כזה בפרויקט אחר מסול שאני רוצה להוסיף reference אומר לו כן בטח אין שום בעיה אז הוסיף reference אוקיי קקulator c שווה newקulator עכשיו הוא אומר לי פה הי תהפוך את זה לו אני בדרך כלל לא אוהב להשתמש בו אלא אם כן יש לי ממש אני רואה את הטייפ המלא של משהו אני בדרך כלל אני לא משתמש בבר בטestטים שלי אז זה שרשרפר אומר משהו זה לא בכלל חומר שחייבים לעשות את זה רואה המון אנשים שהולכים לפי רשפר בלי לינ לדוגמה לוקחים את כל הלופים הופכים אותם ללינק [\[04:43\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=283s) אזלינק זה לא קרי by defaultט לי אישית יש בעיה עם לינק אבל כן זה שאומרים לכם לקפוץ מהגג זה לא אומר שחייבים וכולי c add in in x in y מה לשלוח שני של ארב ש >> בטח שזה לא משנה אז מה נשלח ואחד >> אח אחד ואחד אחד ואחד >> עדיף שניים שונים >> עדיף שני שונים >> עדיף שני שונים אז מה לשלוח >> אח ושתח ושתיים למה שתי שנים? למה שני שנים? [\[05:13\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=313s) אם הסדר משנה >> אם הסדר משנה הוא צודק. >> אם זה היה x כמו שזה בהתחלה אז שזה לא זהx הזה כן אבל זה לא היה מתפל אם היית עושה בתוך הפונקציה בטעות x ועוד x אם היית עושה בתוך הפונקציה בטעות x ועוד >> כן אם הייתי אם הסדר היה משנה של הפרמטרים אז לחלוטין זה סיבה טובה מאוד לעשות שני מספרים שונים אבל למה לא נגיד 42? קודם כל זה מספר שכל הגיקים מכירים זה לא שזה בעיה נכון למה >> 1337 גם [\[05:44\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=344s) זורק בתקיעות >> לא ליט בן אדם אבל מה הבעיה עם ה יש בעיה עם זה כאילו למה לא לעשות את זה >> כשקורים את >> קודם כל כמה זה ביחד מישהו יודע מה זאת הבעיה א' אם אתה לא יודע לעשות את זה בראש אז זה כבר לא יהונטסט מבחינתנו אה זה צריך להיות קרי >> אה תסה 1338 יפה ועוד אחד 1 ש7 אני בכלל אומר לאנשים תניח שהבן אדם שהולך לקרוא את הטestטים שלך הוא רוצח סדרתי שיודע איפה אתה גר אל תעצפן [\[06:18\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=378s) ואז אם הוא קורא את הצד שלך ואומר 1337 למה 1337 מה כל כך מיוחד במספר הזה אני אלך לבית שלו ואשאל אותו זה ככה לא רעיון טוב אז אני אוהב להשתמש במספרים הראשונים שהגיוניים לסצנר הזה אז אם זה posive numers אז השניים הראשונים שאני יכול לחשוב עליהם זה בדרך כלל נתפס המוח שלנו רואה את הפטרן הזה אומר אוקיי הם לא משנים אבל אם הייתי אומר ארבע ושתיים זה פתאום נראה מעניין אני רוצה שזה יראה משעמן אני רוצה שזה יגיד אה אחד ושתיים תראו בלי שזה אוקיי זה ממש ממש חשוב אני לא רוצה שלאנשים יהיו שאלות לגבי הטסים שלי אני רוצה שהם יוכלו לקרוא את זה כמו ספר [\[07:00\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=420s) אמחינתי גם זה סוג של כמו שיש משתנים בלולאות שיש i וJף אחד לא אכפת שקוראים להם i וj פשוט יודעים שזה משתנה זה לא השם שלו לא משנה אז גם פה אבל לפעמים אני לא יכול להשתמש במספר לפעמים כל מספר נראה מוזר אז אני שם את זה באיזשהו משתנה ונותן לו שם נורמלי טוב עכשיו אני צריך את הרultט של הדבר הזה אז אני אעושה פה אstract variable contr alt v כדי לקבל את התוצאה in result [\[07:30\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=450s) ואל שתחו את הספסing cont v זה לא בalך אגב ריש are equ הראשון זה הectד למה אני מצפה יפה זה לא פרה עצמה >> שלוש זה והט זה result זהו זה הטest הראשון שלי עכשיו בגלל שיש ליפר אז יש לי פה test run אני בדרך כלל לא משתמש בטest run הזה למרות שאם אני אעשה את זה אני יכול להרי את הטestטים שלי פה יכול לראות פה את הטסטר למה לא להשתמש בו תני אסביר [\[08:09\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=489s) קודם כל תראו איך זה דבר זה נראה מאוד יפה >> זה של רישרט >> זה של רישרט זה נראה מאוד יפה אבל תשים לב כמה זמן לקח לי להריז טסט אחד מסכן והוא זה והוא זה ואז ה הוא היה צריך למלא את כל האייקונים היפים האלה ואז הוא צריך להראות לי את החלון וכולי אני מעדיף משהו קצת יותר מהירש הטestסטר שלו הוא באמת יותר מהיר מMSסS אבל הוא לא מספיק מהר. כשאנחנו מדברים על [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)"), הפידבק שאנחנו רוצים הוא הרבה יותר מהר מזה אפילו. הRT runner שאני אישית משתמש בו הוא TestDriven.NET. [\[08:41\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=521s) TestDriven.NET זה פלאגין שהוא חינמי בponal edition ועולה כסף בנופal edition אבל יש לו כמה יתרונות על הרנרים האחרים כולל רישה. אבל קודם כל אני אראה לכם איך הוא נראה. זה הסימן הזה פה של הט. אוקיי אם אני מריץ את הדבר הזה עם test driven אז כל האoutput נמצא בקונסול אין לי outputפוט ויזואלי בכלל אולי צריך לקמפל הפארמזה בטח שזה יקח יותר פחות זמן כן בוא נשנה פה משהו נעשה פה רווח [\[09:21\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=561s) לנו ממש ממש אני אוהב אותם נגיד test אומרים זה ההבדל במהירות זה מאוד מאוד רציני אבל יש עוד כמה שיפורים נחמדים בסדר. א' אם אני עושה קליק אם אני מחוץ לטestט אז מריץ את כל הטestטים לקס. אני עושה קליק אם אני ברמת הפרויקט מריץ את כל הטestטים לפרוינקט או ברמת הסולשן. בדרך כלל מה שאני עושה זה אני מריץ את כל הטestטים ברמת הפרויקט ומאותו רגע אני אנסה לא להשתמש בעכבר יותר כדי להריץ את הטestי. מה שאני אעשה לעשות מעכשיו זה יש אtion מיוחד בטest drקר repיט או run את run last action [\[09:58\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=598s) וכל פעם שאני אעשה רש ואני אוסיף חדש אז הטest הזה ייקלל אוטומטית כי הלס אקשן היה להריץ את כל מה שיש בפרויקט בקופני >> זה עושה את זה אני הולך לעשות שורדקאט כדי לעשות את הדבר הזה אז זה לא עושה כרגע את זה אוטומטית אבל אין לזה שורטקאטס אז היום ביזל סטודו אני יכול לעשות שורטקאט לכל דבר שאני רוצה אני הולך לtools options keבורד ופה בשורה אתם רואים פה את הרשימה הזאת פה יש לכם את כל האtion בתוךסטודיו אתם יכולים לחפש מה שאתם רוצים ולבדוק מה השורטקאט הקיים שלו או לשנות את השורקאט שלו אני הולך לחפש את reun test [\[10:38\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=638s) אתם רואים שיש לי רק אחד כזה אני הולך לשים פה איזשהו שורטקאט ke וללחוץ הסינ השורטקאט שאני אוהב זה alt r אבל אתם יכולים לעשות מה שבא לכם ק שמו >> אלט אבל בזל הסטודיו מספיק חכם כדי להגיד לי שזה כבר תפוס על ידי משהו מאוד מאוד חשוב כרגע כבר מלא זמן לא השתמשתי בשורטקאט הזה אז זה בסדר אני אתגבר על זה ואני אעשה אס [\[11:09\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=669s) אוקיי מעכשיו אני הולכת גם לprודאק אני יכול לשנות אותו ולהגיד נגיד פלוס אחד ואני לא צריך לעשות אפילו save אני עושה alt r זה כבר עושה לי save ‏buildד והכל. אוקיי, אני לא צריך להיות בטestטים בכלל. אני משנה משהו פרדקtion ותוך חצי שניה אני כבר יודע מה קורה. אז הוא אומר לי, תשמע, אני רואה את השם של הטest, אני רואה expectד, אני רואה actם יש לי פה את הדבר הזה, זה גם חשוב באטpט כל פעם שאתם רואים את המספר שורה, זה מספר שורה ומספר קול. [\[11:43\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=703s) כל פעם שיש לי מספר שורה, אני יכול לעשות דאבל קליק על שורה הזאת. זה לא קשור לtestל זה פשוט feature של visual studioent ואז אתם יש לי פה בדיוק את הדבר הזה פה את זה אוקיי ואני רואה שהסריות שלי נשמת יוצא יופיע אז אבל זה לא מה שאני אוהב עדיין בטסט רנדר זה באמת כל הפיצ'רים האלה אחלה אבל אני עדיין יכול לעשות את זה גם עם עם הרישרפט testסט הנה עוד דבר שאני יכול לעשות עם כל הרנרים אחרים אם אני עדיין לא מבין למה הטסט שלי עכשיו אני איך עושים פה break point [\[12:18\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=738s) ולהגיד או עם ReSharper אני יכול להגיד debag או עם test driver אני יכול להגיד test with debagger ואז הוא מדבק לי את הtest שלי ישר מתוך studio ואני יכול לעשות step in וכולי וכולי הפיצ'ר הבאמת נחמד זה שעם testing אתה יכול לעשות stepפ in גם בקדפuc גם אם אין לך הטestטים בכלל אני יכול ללכת עכשיו סתם לפונקציה פה להגיד פהפ point או אפילו פה נגיד נניח שאין לי אפילו test אחד בחיים שלי test with debugger [\[12:56\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=776s) הוא אוטומטית מפעיל את הפונקציה הזאת עם reflectiontion נותן לערכים default values ואני נכנס לעשות steping to theפציה אז אם אני רוצה אני יכול לעשות את productiontion c פונקציה קטנה שקורת לפונקציה אחרת עושה לה set into debug with test with debugger ואני לא צריך לכתוב consolול אפליקש יותר לא צריך לעשות שום דבר אני יכול לדמות איזה ערך שאני רוצה את ערך זה אחד הדברים שחוסכים לי המון המון זמן כשבעיקר בלגסו אז זה באמת אחד הדברים הכי יפים בטסרים האלה שהוא נותן את הפיצ'ר הזה ואף testר אף רנר אחר לא נותן את זה [\[13:30\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=810s) אוקיי אז אני רק אבוד שהפעולה האחרונה שלי זה run all testing project ומעכשיו alt r פשוט יחזור על הפעולה הזאת שעלה לגבי testing יש לו דרך טיפה יותר נורמלי כ test results >> זאת זאת הדרך הנורמלית הקונסול הזה >> זאת הדרך הנורמלית מבחינתי אם אני אני רואה את זה בקונסול זה כל מה שאני צריך אני צריך לדעת אם משהו נכשל או לא צריך לדעת שהכל עבר 17 אז אני אוכל לראות את הרשימו שלהם בטח יש לו גם >> לא אין לו יש לו בפה של [\[14:01\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=841s) >> זה הui הזה אני מתכוון הפרס runר שלו יכול לראות שם >> וואלה הוסיף את זה >> אני אני לא מכיר את הפיצר הזה אני רק יודע שאני יכול להרוג אותו אבל וואלה אם יש לו את הפיצ'ר הזה אחלה אבל אני אני ניסיתי עכשיו ולא ראיתי שום דבר אבל אני אומר לכם בתהליך הטd בדרך כלל אתם מתחילים אתם לא מתחילים 17 טס נכשלים אתם באים אתם משנים שורה פתאום 17 נכשלים רגע רגע אנדו אוקיי עכשיו בוא נעשה את זה קצת יותר קטן או עכשיו רק אחד נחשל או אתם מתחילים את זה שנכשל אתם מריצים משנים את הקוד אף אחד לא נכשל זה באנך שלי אבל כרגע אנחנו עדיין לא שם אני רק עדיין ממשיך לקנפג את הסביבה שלי [\[14:47\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=887s) אני אתקן את הבאג פה alt r מצוין שיפט state לסגור את החלון ועכשיו אני יכול לכתוב טestט חדש אני עדיין לא עושה רפאקטורים אבל יש לי פה רצון מאוד גדול פשוט לשכפל את הטestט הזה זה יש לי קצת בעיה עם זה אני מאוד אני יש לי בעיה עםקופסטינג אבל מה שאני אעשה במקום אני אקנק את הסביבה שלי שזה לא יהיה באסה לכתוב חדש [\[15:18\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=918s) אז כדי לעשות את זה אני אלך לרישר פירות כבר ואני אכתוב אלך לtמפל explorer ואני אצור לי tempליate חדש ליצירה של test אז יש לי פה את הכפתור הקטן הזה אתם רואים את זה נקרא טמפליט יצירה של טסט מה שקורה זה שפה אני אכתוב איזה איזה מילה איזה coddewור נגיד test וכל פעם שאני אכתוב test יופיע לי test ואז אם לחץ טפט ואז כל הקפוד שיש למטה יכתב אוטומטית יכול קצת יותר חכם test מה זה [\[15:51\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=951s) תכף נדבר על קונטרול s כדי לשמור את זה כרגע סתם עשיתי פיסט לקוד שלי אוקיי עכשיו אם אני הולך לtest אז אני מקבל את הדבר הזה התחלה טובה כבר ההבדל מסניק זה שאני לא צריך לעשות XML זה כבר ממש ממש ממש וחבר שני שני זה עדיין לא מספיק טוב. מה שאני רוצה זה שהטestט שלי יהיה קצת יותר דינמי. לדוגמה אני אשים פה לא רואים את זה אני שים ככה [\[16:30\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=990s) אני אשים את זה בין שני דולרים unit of y אוקיי מה שאומר שעכשיו זה יהיה דינמי אם אני אחשוב חשוב test אני מקבל את הדבר הזה טוב כואב ככה עכשיו אני יכול לכתוב טמפליטים הרבה יותר חכמים אז מה שאני אוהב לעשות זה לשים פה unit of workרio ו כל מה שבין שני דולרים נהיה דינמי ויש פה עוד איזשהו קיבוורד אחד נחמד שנקרא [\[17:00\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1020s) ופה הקרס יסיים את החיים שלו כשאני מסיים את העבודה פה אז אם אני עושה עכשיו test אני יכול לכתוב אוקיי סנר מה היה הסנר שאני רוצה לבדוק עכשיו >> אוקיי נגטיב ‏first מה שמינוס אמור להגיד מה מינוס בעצם אומר תחשבו [\[17:36\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1056s) כי מחר er value זה יהיה מינוס3 אני אכתוב פה מ1 אז הטest שלנו מאוד cלמation אנחנו צריכים להגיד את זה כדרישה אם אני נותן לו משהו נגטיבי הוא נותן לי איזשהו er number משהו שמסמל אוקיי אז עכשיו אני אעשה newקulator structable c יש לי כבר בעיה עם השי הזה נכון נעשה פה entulator [\[18:11\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1091s) מה ניתן עכשיו >> מה >> מינו2 מ ש >> מה דחיף >> אה מינוס מינוס לא ב >> ואחד >> מינוס1 ואחד >> מה אתם אומרים זה נראה מעניין מדי >> מינוס ושת >> כן גם >> מה אתם אומרים נראה מעניין מדי >> אה מה עם אפס >> גם מעניין מדי >> כי זה בעיה כי אני כל מקור מקבל מינוס 2 מינו 2 >> 2 ומינוס2 [\[18:45\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1125s) כמה תרוח לאפס נפתור של שני מספרים לא מינוס אם תן אחד מינוס שתיים תמות מינוס איתך חברות החלטו אני בכוחן צודקים אבל יש לי עדיין בעיה הרוצה סדרתי יבוא יגיד מינוס ש ושת פה משהו מיוחד >> מינוס שפ מ2 שפ >> אין פה מספר טוב אין פה מספר טוב אני אגיד מה שאני אוהב לעשות זה ככה זה ונעשה פה ‏variable in su posive [\[19:16\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1156s) פה מינוס אחד וגומר עניין אוקיי יותר מדי הדיון הזה זה אומר חיל להעביר אומרים אם אם יש ספק אז זה אין ספק גם מינוס אחד פה בלי >> כי זה יחזיר מינוס אחור חזיר מינוס אחד יודים לחשוב שתחס מינוס אחד כי קיבל ששם נגטיב פה זה גם אחת טוב נגטיב זה גם >> השאלה היא כזאת אם אני עושה פה מינוס אחד הטסט שלי אמור להיכשל או לעבוד [\[19:48\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1188s) אב >> לא עשיתי עדיין את הסרט נכון בוא נצא את הסרט ואז נראה מה מה קורה זה שאנחנו יודעים שזה מינוס אחד עדיין לא חשוב לנו אנחנו צריכים לדעת שהסימבול ומינוס אחד עם אותו דבר אז תכף נראה איך אנחנו פותרים את הדבר הזה הסט עכשיו הנה הI השני שיש את העניות אם אתם לא אוהבים את equal אתם יכולים לעשות assert [\[20:19\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1219s) In result that result is equ to מינוס 1 בסדר ירוץ לא ירוץ מסע יותר בום עבר אבל פה באמת אם אנחנו יודעים ש אני רואה פה מינוס אד ואני רואה פה מינוס אד עד עכשיו הטסט הזה עוד פעם לא קרי אוקיי ולכן אני יכול להגיד בוא נגיד ככה אם אני יכול להגיד שזה שהultט is equal to אcat [\[20:56\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1256s) Er איזשהו ‏in static ש אוקיי עכשיו שימו לב תראו גם השורה הזאת יותר ארוכה אני אישית לא אוהב את הביא את זה אני אישית הרבה יותר מעדיף את [\[21:26\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1286s) As equalator er value כי פה אני רואה מה אמור לקרות רק בסוף השורה ולפעמים השורה יכול להיות מאוד ערוכה ופה אני רואה את זה הרבה יותר טעים וזה באמת החלטה זה כבר עניין של טע אבל גם פה אני מבקש תהיו קונסיסטנטים אם אתם חטים שאתם משתמשים באחד תשתמשו רק באחד מהם פה הקונבנשנ שאתם משתמשים קבוצות מאוד חשוב שלאנשים יהיה קל לקרוא את הטestטים אחד של השני >> מישהו יש בעיה להשתמש בריקול [\[21:58\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1318s) יופי מעולה >> נבחר אבל >> אני יכול גם להגיד פה מינוס אצה פה מינוס2 אני מור ועכשיו גם פתרתי את הבעיה שאני רואה אני יודע שזה מינוס ואז טכנית יש לי בעיה עם זה וגם פתרתי את בעית הנגטיבי >> אבל לא השתמשת בסך בקוד >> במה לא השתמשת בק >> זה כבר רפקטורינג קודם כל אני גורם לזה לעבוד זוכר [\[22:28\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1348s) עכשיו אני יכול גם ללכת לקודש ולהגיד אוקיי אני יכול ללכת ולהחליף את זה בארוב כל הטestטים עוברים אז את יכול להחזיר עכשיו שנית עשיתי ריפקטורing אני בודק שלא שברתי שום דבר אל תעה הוא שאני עושה ריפקטורing אחרי שיש לי טestingים לא לפני כי אם אני עושה ריפאקטורing בזמן שהט שלי עוד נכשל אז אני לא יודע אם הוא ממשיך להיכשל לעובר בגלל מה שעשיתי אז הטמפטליט הזה חשוב עוזר מאוד הטest הזה נראה די סביר פשוט בגלל הפרונטים הגדולים זה נראה ארוך מאוד [\[23:02\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1382s) אמ שאלות הטסט הטestטים שיש לי בינתיים הם בסדר שיש לי משהו שדה לי לעשות >> ואיך תשובה חיובית גם אם לא היה אקספש מינוס שח יוצא גם מינוס ולח בלי שיהיה טאבליק ש >> אוקיי אז אני יכול זה באג לדעתך >> זה אומר שהטסט לא באמת כאילו אני לא יכול לדעת מכאן שבאמת הפונקציונליות הזאת אני יכול לדעת מכאן לא >> מכאן אני יודע שהחיובי עובדת אבל אני לא יודע שיש את הבעיה של הירור רנדלינד למטה כלומר אני לא יודע שבאמת זה עובדים אני >> אוקיי מינוס שלוש >> זה בסדר >> אחלה [\[23:44\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1424s) >> אבל אם מלכתחילה היית כותב 1337 זה לא היה קורה >> כאילומסמספרים שהם קטנים הם יש יותר סיכוי שבמקרה עלית על איזשהו מספר מיוחד כמו למשל פה מינוס2 ואחד במקרה עליתה על משהו מיוחד אם אם לכתחילה אתה כותב טסטים עם מספרים שהם מופלצים, הם איזה 1000 ומשהו אז אז יש פחות סיכוי שהטestט יעבור בטעות. אוקיי? אפשר יש יש יש איזשהי אמת בזה אבל אני מעדיף לטות לצד של הרדבילי ולגלות אם יש לי בעיה אחר כך במיוחד אם אני אוהב testבן אני אגלה את זה מהר מאוד אבל הרדבילי בלי רדבילי זה לא משנה כמה הטestטים שלי נכונים כי אם אף אחד לא מבין למה הטסט שלי נכשל מחר זה לא משנה כמה הוא נכון לכן הרדבילטי זה אחד הדברים שהכי חשובים לי כרגע [\[24:31\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1471s) אם אני יכול לקבל רדבילי ונכונות תוך כדי אני מעדיף את זה לכן אני מתחיל מרדבילי ואחרי זה מקסימום אני אשנה את זה לנכונות תשים לבגיד הוא מתא את הבאג הזה אבל אם אם הפיצ'ר הזה עדיין לא קיים אני צריך להתחיל ממש שנכשל ואז לגרום לו לעבוד נכון ואם הייתי ואם הייתי צריך להתחיל ממשהו שנכשל אז הייתי כותב את הקוד בצורה אחרת זאת אומרת הייתי מגלה שיש לי פה איזשהו משהו שאני מצפה לו בכל מקרה או שהייתי כותב טestט אחר שמוכיח שביתן שני ויוז אחרים אני אקבל מינוס אחר אבל בtd הייתי יכול להגיע למצב שבו הטestט הזה משקר לי כי טestט אחר היה מוכיח שיש פה איזשהיא נכונות אחרת נראה לי שזה עניין של קונבנציה אם כולם יודעים שמספר גדול לא יודע אפילו מחליטים ל איזשהו מטווח של מספרים שהם בטestטים לא יודע אם כולם יודעים שזה בסדר לשים מספרים גדולים אז אז זה נראה לי גם נכון יותר וגם זה לא >> כל זמן שזה קרי אין לי שום בעיה אם נגיד יש לך איזה קונסט של מספר גדול שאתה אוהב אז תשתמש בקונספט אין לי שום בעיה כל זמן שאני מבין בטסט מה לז זה למהור לקרות [\[25:31\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1531s) ולמה זה קורה אם אני רואה מספר גדול אבל אני לא חושב זה בראש זה בעיה אני רוצה שיהיה לי לקרוא את זה ולהגיד שאני יודע מה עומד לקרות. אם אני צריך לשאול אותך מה זה המספר הזה אז כבר יש בעיה כי אני כי הטסט לאט לא מספיק מובד. אוקיי? >> אם מכפילים ב10 למשל זה גם >> מכפילים את מה ב-10? >> את כל המספרים. >> אין לי בעיה להכפיל ב-10. אני גם יכול להיות ככה. מינוס 10 ו-30. >> כן. אפשר לחשב את זה בקלות. זה קר. >> נכון. אבל אבל יש יש אבל זה משהו שחשוב להבין. אם אני יכול להוכיח את זה מספרים יותר קטנים בTD אני מעדיף כי יכול להיות שמספרים גדולים זה עוד פיצ'ר אתה מבין אוקיי >> מכ שמדובר תחשוב על פס של טס ולכן ככל שזה יותר פשוט זה רוב סיפים שזה אינפרנטלי [\[26:14\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1574s) ומכיוון שהרב פעמים אתה לא יודע לאן תגיע עם הדברים האלה אז אני מעדיף להתחיל מהדברים הפשוטים אם אני מתחילים מהדברים הסמוכים יכול להיות שכבר עשיתי לעצמי יותר מדי עבודה כדי לפתור כן >> איפה תגיד מה לגבי אם הייתי לגבי הקראיות אם הייתי אומר פונקציה get ‏number get posive number מחזירה לי כל פעם מספר חיוקי אחר >> האם היית משתמש באיזשהונדום נבר >> האם כן זה נחשב פרקטיס שהוא ממש לא טוב כי אז אי אפשר לצפות בטסט לעבור או שזה נחשב כי זה יכול לה >> אני יודע שהרבה אנשים משתמשים בזה אני אישית לא אוהב להשתמש בזה מבחינתי זה לא [unit test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1 "Defining unit testing, step by step (The Art of Unit Testing, 2nd ed., ch. 1)") אין לי בעיה להשתמש בזה אבל אני לא שם את זה בפרויקט שנקרא unit test אני שם את זה בפרויקט שנקרא inration test בגלל שאין לי שליטה על הרנד ואם מחר הטest שלי מגלה בג נורא קשה לי לשחזר את הטest אתה אומר שכל כל test וניטest חייב להיות החשיטה עצמה הוא חייב להיות צריך להיות prקctable >> רגע מה זוג יכול להיות האם הוא גדול מאפס [\[27:08\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1628s) >> אבל אני לא רוצה שיהיה לי לוגיקה בטסט אם יש לי לוגיקה בטסט יכול להיות גם בג בטest כמו nrq is greater than משהו כזה >> יש rד אבל אני רוצה לדעת את המספר הפשוט המטרה שלי עכשיו היא הטest הכי פשוט ואם זה יותר גדול אולי זה לא המספר הנכון זה הדקה שצריך לזוג אם גדול מאפס כמו שפה זה צריך להיות מינוס אם בוא אגיד לך אם אתה תגיד גיע לרנדום בוא נניח שאתה מיצר שני random numers איך אתה איך אתה יודע שהרכיבו אותם בלי בלי לשחזר את הלוגיקה של הפרדקtion בטestטים [\[27:38\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1658s) אוקיי עכשיו אם אתה משחרר את הלוגה של הפרודקש בטestטים אתה עושה את הפלוסים בעצמך בטסט >> יש לך את הבאג הזה ויש לך באג בפודקצ אתה משחזר אותו גם בטסט שלך עובר אתה לא מגלה את הבג לכן אני תמיד משתמש בדקed values כדי לדעת מה אמור לקרות כי זה הend resultלט שלי אני לא רוצה לדעת איך קיבלתי אותו >> גם יכול להיות שהטest פעם יעבור ופעם לא יעבור אתה עושה alt r זה עובר alt r זה לא עובר זה לא התנהגות ש לא קונסיסטנטי אבל כן רנדום זה בסדר זה פשוט לא אז כדי לדחוף developופment אני לא משתמש ברנ כי אני רוצה משהו קונסיסטנטי שמוכיח לי שמשהו לא בסדר והמשהו הזה אחרי זה תמיד יעבור אחרי זה אני אוסיף את הטestטים עם הרנדם בפרויקט מופד אין לי שום בעיה עם זה אבל אני לא אגיד שזה יוני testing בגלל שאלה באמת טestטים שלפעמים יכולים לעבור ולפעמים לא וכשהם לא אז נורא קשה לשחזר אותם כי אז אני צריך לתחוד לעשות לוגינג מה באמת שלחתי מה יוצרתי כל הטestט יהיה הרבה יותר מסובך אז אז טestטים מסובכים אני לא כותב פה פה זה טestטים שהם קריאים ועוזרים לי לדחוף את הפיצ'רים שלי קדימה אוקיי בגלל זה אני גם לא כותב טestטים עם פרדים כי גם בפרדים אין לי שאני הטסטים [\[28:38\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1718s) יקחו הרבה יותר זמן טסטים שאני מריץ צריכים להיות מהירים צריכים אני צריך לקבל תשובה כמה שיותר אה עוד שאלות כמובן שמה שאתם רואים עכשיו זה דוגמה לפיצ'ר הכי פשוט שאנחנו פעם יכולים לחשוב עליו אבל צריך לדעת לכתוב טסים גם לפיצ'רים האלה הרבה פעמים הבדנ בלוק של הרדילity ומטביל שם שמשוים גם בטestטים המסובכים אבל הטest הזה הוא עדיין לא maable יש עדיין בעיה פה אני עדיין קורא לקונסטרקטור עכשיו יש כמה featureים ב-NUnit וגם בMS test שעוזרים לנו לפתור את הבעיה של ה של repating yourself יש אבט שנקרא setup [\[29:14\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1754s) לא עשה culture setup setup זה בעצם אטריבט שאומר למתודה שמתחתיי אוקיי ‏before הקוד הזה יקרא כל פעם right line before אם אני אריץ עכשיו alt r אתם רואים שה הקוד הזה רץ פעם אחת לפני כל test [\[29:47\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1787s) אני יכול להשתמש בקוד הזה כדי להתחל משתנים ברמת הקלאס ואז אני מגדיר אותם פעם אחת ומתחל אותם באותה צורה לפני כל טestט זאת אומרת אני יכול להגדיר את אקulator C ברמת הקס אבל אני לא רוצה להתחיל אותו ברמת הקלס אני רוצה להתחיל אותו ברמת הסדר שווה יופי שר עדיין לא כזה חכם [\[30:19\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1819s) ופה אני יכול להגיד C שווה קulator עכשיו אני לא צריך להתחיל את קלקולטור בכל הטestטים פה ופה אשרה את זה לC כל הטסטים עדיין עוברים ועכשיו אם מחר אני משנה את הקונסטרקטור שלי ומסיף לו פרמטר אני לא צריך לשנות עכשיו את כל הטestים אני משנה רק במקום אחד והמטנability שלי עולה [\[30:49\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1849s) כביכול פה שלב אבל יש פה בעיה יש עדיין משהו שאני לא אוהב בטסטים האלה יש לכם רעיון אם אתם עושים רויwתם מסתכלים על הטestט הזה מה אתם רוצים יש לכם איזשהי מחשבות חיוביות או שטליות >> אה COF is C נכון זאת בדיוק הבעיה שכדי להבין את הטסט הט אני עכשיו צריך להסתכל בשני מקומות כן אני יכול לשים את העכבר שלי פה ולראות שזה קל לי לטוב אבל אני לא יודע מתי הוא נוצר כמה פעמים כבר השתמשו בו האם באמת שמו אותו בסע [\[31:21\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1881s) אז אני לא רוצה שבן אדם יצרך לקרוא שני דברים כדי להביא את הטסט שלי אני רוצה שהטest שלי יהיה אקספליסיט ומובן לחלוטין ולכן אני ממליץ לא להשתמש בסדר כמעט אף פעם רק בגלל שהפיצר הזה קיים זה לא מה שמונלץ להשתמש בו במקום זה אני אעשה ויד את כל הדבר הזה אופס דבלתי [\[31:56\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1916s) הנה יפה יש לי פה עוד שני טסטים שלי אוקיי ווריד את כל הספ בסדר הבעיה שלי עכשיו זה עדיין חזרתי לבעיית המטבity נבדוק שהכל עדיין בסדר אבל במקום להשתמש בסטא מה אני יכול לעשות כדי להיות גם readable וגם mainable במקום זה אני מעדיף להשתמש בקטור פשוט לעשות מדקול עד למתודה נקרא להט [\[32:30\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1950s) בגלל זה גם חשוב לי לעשות את זה כמה שיותר מוקדם אחרי שיש לי שני טסים לא שלושה כדי שהעלות של לשנות את זה אחר כך היא תהיה מאוד נמוכה את זה בזמן שאני עושה את זה עכשיו כל הטסטים שלי עדיין עוברים הטest שלי הוא readable אבל אם מחר אני מוסיף פה דברים לקונסטרקטור אז אני יכול לתת פה defaultט valאפט לי מר כן אכפת לי מה שאני שולח לקונסטרקטור אני יכול לעשות טסטים במיוחד עם הולז האלה ולא להשתמש בפאקטורים האיכות הזה אני גם יכול ליצור פקטור מוד עם קטור יכול לעשות פקטור מוד עם קולטור שכבר קראו לו שלוש פעמים אם אני רואה שאני חוזר על עצמי אבל רק אחרי שאני רואה שאני חוזר על עצמי [\[33:06\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=1986s) כן את השאלה שמעתי מישהו אומר משהו >> עדיין נקרוא כאילו לראות את הקוד בשני מקומות עדיין ניצח פה להיות ל >> לא אני רואה פה שאתה מייצר לי כל יותר חדש אני לא צריך לקרוא ש אני יודע שהוא חדש אז אני לא צריך ללכת להסתכל אוקיי אם אני באמת ארוצה לדעת איך נראה חדש אז אני יכול להסתכל אבל בדיפa יש לי הרבה יותר מידע אני לא צריך אני כבר יודע שגם יש לי קלקulator אני יודע מה הטy שלו כי זה לא [\[33:39\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=2019s) וגם אני יודע שהוא חדש כי כתוב make לא כתוב גט אם כתוב גט אני לא יודע אם הוא חדש אוקיי בואו בואו בוא נוסיף עוד פיצ'ר לדבר הזה אני עדיין לא עובד test driven אבל כרגע יש לי פה גם איזשהו פאג נכון נכון? זאת אומרת אני כרגע לא בודק את הפרמטר השני. אז בוא נניח שיש לכם קוד וקלייתם בג כזה. אם אני רוצה לתקן את הבאג, אני לא אני לא אלך ואתקן אותו. אני קודם כל אכתוב לו טestט. קודם כל אני אנסה להכו את הבאג הזה. [\[34:10\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=2050s) אז עכשיו אני יכול לבוא ולהגיד, אוקיי, יהיה לי בגדול את אותו טestט, אבל אני אשלח פרמטרים שונים, נכון? זאת אומרת בגדול זה נראה כמעט אותו דבר אפילו השם שלו אמור להיות אותו דבר הדבר היחיד שמתחלף זה הערך של זה וערך של זה נכוןס >> וסקנד פרמטר נכון אז אני יכול לעשות את הדבר הזה וזה באמת מהר מאוד אני אגיע למצב שבאמת יש לי שני טestטים שניהם קריאים שני אבל יש דרך יותר פשוטה לעשות את הדברים האלה אם באמת יש לי את אותו טestט [\[34:50\]](https://www.youtube.com/watch?v=80H_AvRX6oM&t=2090s) אז אני לא חייב לעשות את הדברים בצורה הז ## Related - [Replacing beforeEach() completely with factory methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2) · The Art of Unit Testing, 3rd ed., ch. 2 Book section on replacing setup methods completely with factory methods, the same refactoring done to the calculator tests. - [Magic values and naming variables](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_169) · The Art of Unit Testing, 3rd ed., ch. 9 Covers magic values and naming variables, matching the lesson's choice of plain inputs like 1 and 2 over 1337. - [Avoiding logic in unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_141) · The Art of Unit Testing, 3rd ed., ch. 7 Book section on avoiding logic in unit tests, as the lesson advises when keeping random values and logic out. - [Writing your first test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec4) · The Art of Unit Testing, 2nd ed., ch. 2 Writing a first NUnit test in C#, the same step the lesson takes with the calculator class. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Avoid setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162), ch. 8 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 #### The Art of Unit Testing, 2nd ed. - [First steps with NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3), ch. 2 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1), ch. 1 [Previous lesson Syntax](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/syntax/) [Next lesson Test Cases, String Asserts and more](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/test-cases-string-asserts-and-more/) --- title: "Test Cases, String Asserts and more" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/test-cases-string-asserts-and-more.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/test-cases-string-asserts-and-more/" tags: [] author: "Roy Osherove" description: "Lesson 4 of 22 in TDD in .NET in Hebrew (Day1 - Unit Testing and TDD 101), 34:49. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Test Cases, String Asserts and more 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day1 - Unit Testing and TDD 101 Lesson 4 of 22 Duration: 34:49 [Watch on YouTube](https://www.youtube.com/watch?v=_BrBkzT-25U) Spoken in Hebrew ## In this lesson Roy Osherove merges similar tests with [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)")'s [TestCase attribute](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec5 "Refactoring to parameterized tests (The Art of Unit Testing, 2nd ed., ch. 2)") and compares ways to test an exception: try/catch with Assert.Fail, the [ExpectedException attribute](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2 "Checking for expected thrown errors (The Art of Unit Testing, 3rd ed., ch. 2)"), which can pass when another line throws, and Assert.Throws with a lambda. He treats a [TearDown](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_171 "Setting up and tearing down (The Art of Unit Testing, 3rd ed., ch. 9)") as a sign of an [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)"), to be kept in a separate project, and names the continuous test tools AutoTest.NET, NCrunch and Mighty Moose. He then introduces the three [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") steps and starts a calculator memory feature test first. ## Transcript 4,694 words [\[00:03\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=3s) ופה אנחנו נכנסים לאפצ'ר שכרגע חסר ב-MSTest שזה הנושא של parametr test אני יכול לקחת את הדבר הזה ולהגיד עכשיו יש לי פה פרמטר לפונקציה עדיין אף אחד לא שולח אותו כי הוא עדיין לא מספיק חכם תכף אני אראה לכם איך אני אשתמש בו זה y שתי פרמטרים [\[00:34\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=34s) ו אני בשניהם אני מצפה אפילו לאותו אר נכון אז אני יכול להגיד עכשיו במקום test אני משנה את זה לtest casס אני אומר הטestק casס הראשון אני שולח מינוס2 כל מה זה המינוס3 ו2 או 1 ואני מצפה חזרה למינוס1 אחד נכון אני אין לי פרמטר על זה אני תמיד מצפה לר כביכול יש לי עכשיו את אותו test [\[01:06\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=66s) עשיתי רפקטורing הטest הזה רץ בדיוק אותו דבר מה שיפה בטסט זה שאני יכול לשים מטפל test cas אותה מתודה וכל אחד מהם הופך לטסט בנפרד אז אני יכול לעשות ככה אני יכול להגיד אוקיי עכשיו נעשה אחד זה מינוס 3 הטסט הזה עדיין אמור לעבור מינו עזר עכשיו יש לי תשימו לב returns error value עם 1 ומינוס 3 נכשל אוקיי [\[01:37\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=97s) ועכשיו אני יכול ללכת ולתקן את הפיצ'ר הזה >> יש פה משהו שאני מכיר צריך שדבר על ההתרדה >> ההתרדות זה משהו שאני נכון y נתן מאפס עד הכל אמור לעבור עכשיו שלושה פסט עכשיו בוא נדבר על מה מתי לך אם אתה חובר חזרה עוד לפני שעשית את התיקון הזה של אור y קטן מאפס כן >> ובטעות עשית את הטestט כמו שאמרנו קודם >> מינוס אח >> לא אחד במינוס שבעצם היה מחזיר התוצאה והטסט היה עובר כן >> אז בעצם אנחנו נתקנים כאן באותה באותו מצב שוניט testing היה אמור לפתור לנו שאנחנו יכולים לסמוך על הקוד ב-100% שבעצם פאקטור גדול שאנחנו עושים אנחנו מריצים את היוקסטים [\[02:24\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=144s) ויודעים שהסנריוס שאנחנו מצפים יעבו >> אתה אתה אתה אומר שעריפת כלום שעשיתי לשבור את הטסט זהו לא אני אומר מה שכונ שהכתיבה של הטestטים צריכה לעשות איזה רו מטורף כאילו כדי שאפשר לסמוך על זה ב-100% כדי שאתה לעבור על כל הסנך איזשהו >> טוב צריך לזכור שאנחנו עדיין לא עושים את [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6 "Test-driven development (The Art of Unit Testing, 2nd ed., ch. 1)") בטDD ההרגשה לגבי הטest משתנה כי בTD אתה מתחיל מטestט שאמור להיקשל ואז הוא אמור לעבור ואם אתה ואתה תגלה בד מאוד מהר כי אחד מהם לא יקרה >> שמנו מלא ואז אתה סומך על הט >> נגיד שהיית משנה עכשיו היית עושה רפאקטור והיית משנה את ה לא היית עושה את הטפס והיית משנה שם את הור למינוס שת זה היה פקטור אז הטest היה עובר ועדיין לא הייתה מודע לזה שאתה לא בודק אם הyשלילי ש >> נכון אם הייתי מחזיר מינוס שת אבל הייתי מודע לזה שאני מחזיר מינוס ש עשך [\[03:16\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=196s) נגיע לנושא של אבל טD הרבה פעמים אתה מחזיר כדי לרום לכל לעבור אבל אתה מוכיח בטest נוסף שמשהו לא בסדר שם >> זאת אומרת הטestטים מג מגבים אחד את השני אבל הם מראים לך עבודה אינטרמנטלית המטרה היא תספור לא רק להוכיח נכונות המטרה היא להוסיף פונקציונליות אבל בצורה אינטרמנטלית עכשיו במקרה הזה בוא נניח שאני עכשיו אני עכשיו יכול להחזיר פה מינוס שת לשמ את הקס את האר ואם היית אם היית מסיר את קטן נפס זה עדיין היה >> אם הייתי עושה פה מינוס שת זה היה עוד פקט >> כן אבל הוא y את הנפס עדיין ק >> אני מסכים איתך שאתה יכול לכתוב [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") ושעדיין יהיה לך בוא [\[03:53\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=233s) >> זה לא משהו זה הולך להמשיך לקרות מה ש אבל ההבדל הוא בתרבות התרבות הארגונית אומרת שכשאני מגלה את הבאגים האלה אחר כך ואף אחד לא אומר שאתם לא תגלו באגים אחר כך להפך אתם תגלו באגים פשוט תדעו מה לעשות איתם אחר כך הרבה יותר בקלות זה שאתם תוסיפו את הטestטים לפני שאתם פותרים את הבאגים ואז הבאגים האלה אם הם יחזירו אתם תגלו אותם ודרך אגב בד של טttנושא של מתי להפסיד לכתוב טestטים אין איזשהוא משהו מוצג שעובר את זה היום מתי אתם חושבים שהקוד שלכם עובד מתי אתם מגישים את הקוד לסורס קונטרול או לד [\[04:29\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=269s) היום בצ'קין אנחנו שמים ש >> אנחנו עושים טס >> מה גורם לך לחשוב שאתה יכול לעשות צ'קין לכל >> אנחנו עושים טסים פה יש לך פשוט יותר סיבות לחשוב שיש לך סיבות לשים שקטו זה ההבדל זה קור אותך לרמת ודאות יותר גבוהה אבל זה לא ודאי >> זה לא תהליך מדעי זה לא תליך מדעי זה תהליך אנושי >> בגלזה אומר שזה עדיין מסוכן כי אתה יכול לסמוך על זה הרבה יותר נגיד אם אתה עושה זה בסדר זה לא זה מסוכן בהתחלה כי הרשת ביטחון שלך מאוד קטנה אבל יכול שאתה תגלה את הדברים אתה גם אתה פשוט מאבא את הרשת כל הזמן >> ותזכור המטרה שלך היא לא רק לבדוק שזה עובד אלא להוסיף את הפונקציונליות [\[05:06\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=306s) אז גם אם לא הכל עובד וחלק לא עובד באמת יש לך עדיין משהו הרבה בצורה הרבה יותר מהירה ממה שהיה בך קודם >> אבל אתה יכול לרשות לעצמך לעשות שינויים גדולים יותר >> ככל שאתה תרגיש יותר בנוח בהתחלה אתה לא תרגיש בנוח לעשות שינויים גדולים כי הקover שלך יהיה מאוד מאוד זה גם מאוד עוד לא מסתכל על התהליך בוא בוא אני רק >> אנחנו עדיין לא עושים את התגיד שבאמת הטסטים עוברים ביו הרבה יותר מסי >> אבל זה לא התהליך שהיינו עושים אנחנו היו נוגעים לתוצאות אחרות לגמרי בגלל שמה שאני אומר עכשיו זה את הPI אני לא מלמד את התהליך הדה [\[05:38\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=338s) הוא התמודד עם החשש שלך כי כרגע החשש לא מחובר לתהליך עוד אין דלי >> כן סב קיצור אתה צודק פועל >> לא הוא לא פועל אני מעודן את התהליך ברגע הוא אז נוכל להיות אה הוא צודק בקטע הזה שהטestטים הם אף פעם לא ארובה לזה שהפוד עובד אבל הם הם עוזרים לך בביטחון שהפוד עובד אבל אם לא עושים TDTd אז יש הרבה יותר סיכוי שהטestטים ישרים מסכים יש דרך לצאת שמות [\[06:08\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=368s) ש לתת שמותס מסובך אם הוא מסובך אני אני מאמין שהדבר שהכי קשה יש שני דברים מאוד קשים בטestטים למצוא שמות טובים ולמצוא פרמטרים טובים אוקיי כל השאר הוא היה יחסית קל כבר רגע שאתה יודע איך לבדוק את המערכת שלך זאת אומרת הדבר השלישי הכי קשה זה להסתכל על קוד שאתה אף פעם לא בדקת ולנסות לכתוב את הטestט הראשון שלו ואז זה להבין את הפאטרן איפה לשלוח מה לצפות איפה הנדרי resultלט שלי וכולי וזה יכול לקחת גם שעה שעתיים אה אבל בטestט הבא זה ברקח שתי דקות בטסט הבא זה 30 שניות [\[06:45\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=405s) >> אבל שם טוב לטestטest casס >> לטest casס שים לבest casס מה שאני הייתי עושה הייתי עושה לזה עודפקטורing הייתי משתמש פה בקונסטנט כי זה לא קר מבחינתי מינוס של זה לא אומר לי שום דבר אוקיי אז הייתי עושה מפה קונסט שם פוזיטיב שם נגטיב אז הייתי אומר וואלה אני רואה פוזיטיב פה ופוסיטיב פה ונגטיב פה ונגטיב פה וזה ואז מבחינתי זה הרבה יותר טוב אבל צריך לזכור שבטest casיס באטריביוטים אתה יכול לשלוח רק דברים שהם compiled אתה לא יכול לשלוח כבר לזינרים אתה לא לא יכול לשלוח delגatס או דברים כאלה [\[07:18\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=438s) עוד שאלות אם שם פה קונס אתה תראה בס תראה בכונס או את הערך שלו כן ש אתה תראה את הערך שלו אבל אני לא בטוח אפילו לא שמתי לב כי בדרך כלל איך שאוני מגיע לדברים פה עם לא יודע בדרך כלל לא מגיע לערכים כאלה לא יודע למה רק בדמוים הסתם כי בדרך כלל הטestטים הם קצת יותר קריאים כי הם קצת יותר אמיתיים אני רוצה להראות עוד פיצ'ר חדש אלה כן יש עוד שרט [\[07:49\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=469s) לא פיצר חדש ב-NUnit פיצר חדש מבחינת הקורס מה קורה אם יש לי קוד כזה if x גדול מ1000 אז throw new exception I can't do that אוקיי מי שמכיר טוב מי שלא מכיר את קודיסה בחלל [\[08:39\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=519s) אוקיי אבל איך אני בודק פיצ'ר כזה אז ופה חשוב לזכור שבפריים יש היום כמה דרכים לבדוק דברים כאלה קודם כל איך אני אכתוב את הטest הזה ‏test addig number first over מה שמזכיר לי שלא שנינו את השם הזה פהפוד עוזר לפוסות האלה מהבי זה קצת [\[09:16\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=556s) אמ ש מבחינתי אני אריץ את זה אלפי פעמים ביום את האלטר הזה כן זה אמור להיות מהיר אמור להיות לזה firstold זורק exception אז אני עושה varable ‏C C מה זה מה וחצי [\[09:46\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=586s) השאלה >> 1000 מה >> max ועוד אחד >> מקס ול ועוד אחד הבעיה היא מקס ולח שהפלוס הזה מרגיש לי כמו לוגיקה אני לא רוצה אני לא רוצה שיהיה לי דינמי אם אני יודע שבד אחד זה הראשון אז אני אשנה את זה אבל אם אני רואה שמץ אני מתחלף כל הזמן אני אשנה ס בדרך כלל זאת לא כזאת בעיה אה לפעמים אני מסכים איתך שמשתמשים בקונס פלוס אח אצלנו זאת עדיין לבית [\[10:16\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=616s) 1001 ו >> סביב 100 ו2 אני רואה 100 ו2 אבל זה כבר את העניין של טמפ אצלכם יכול להיות שכבר הייתם עושים פה אני צריך לקבל את הול כי אני מקבל פה אפtion אז איך אני בודק את האספtion אז ככה פעם אני אספר לכם שתבינו את ההיסטוריות פעם בג'אבה היו עושים את כל הדבר הזה בטריy catch אחד גדול alt ry catch exception e ואם הגעתי לc [\[10:52\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=652s) בטח com successס הוא לא היה צריך comנ כי כתוב לי בשם של test אבל אם הגעתי לפה אני עושה assert עבודה fail dude where אוקיי עד R אפס עכשיו זה בעיה נכון זה בעיה טestטים שאחרי שאתה שאתה כותב אותם אחרי הקוד יופי אז זהפס איך אני יודע שהטest הזה באמת בודק את הדבר הנכון אז מה שאני הולך לעשות עכשיו זה אני אשים פה promטר ס [\[11:27\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=687s) אני רואה את הטest שלי נכשל ואז אני יודע שהטest הזה באמת בודק את הדבר הנכון אה alt אוקיי אז לקחת לי עוד חמש שניות מהחיים שלי אבל אני יודע שהטest הזה הוא נכון אמ אוקיי אז הטest הזה הוא באמת מבחינת מבחינה טכנית הוא נכון אבל מבחינת אדabity הוא די די די לא משהו אז ב-NUnit פטרו את זה בצורה מאוד נחמדה במקום בנוסף לטest שמים [expected exception](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6 "More NUnit attributes (The Art of Unit Testing, 2nd ed., ch. 2)") [\[12:01\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=721s) ואת ה-typeפ של הceptפtion שאתה מצפה לו כי במקרה שלנו זה אספtion במקרה שלכם זה יהיה של אקספtion אמיתי שהמערכת זורקת ואז צריך עכשיו להוריד את כל הטריק catch כי מה שאטed exception עושה זה תחשבו על זה הוא הוטף את כל הטest בטריק אחד גדול ברמת הרע עושה alt וואלה rפס אבל יש לי בעיה אם זה נכון אני לא יודע מה קורה alt הופ אופס זה לא מה שהתכוונתי זה גם לא מה שהתכוונתי [\[12:32\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=752s) רוצה ‏one failed system exception was expected אוקיי לבדוק את ההג >> מה >> אפשר גם להוסיף את ההודעה את ההודעה של המage של הceptפtion כן אתה יכול גם להרגיד מה תהיה מה יהיה המage אבל שם יש בעיה נוספת שאם אתה מחליט בדיוק מה הסטרינג ומחר הסטרינג הזה משתנה נגיד יש לו עודספיס בסוף אתה לא יכול לעשות קונטינס או דברים כאלה אלה אתה לא יכול לעשות דברים דינמיים [\[13:05\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=785s) אז נדבר על איך כותבים את זה אוקיי אז הסט הוא באמת נראה שהוא נורא מפשט את התהליך אבל יש איתו בעיה יש אתו בעיה גדולה מאוד של טסט מי ש יכול להבין מה יודע שזה הקספ של הנכון יודע שזה בא מהשורה הנכון >> איך אני יודע שזה בא מהשורה הנכול זה הדבר הבעייתי פה מה אם היצירה של מייקל יותר זורק לי את אותו טיים של אקספ של מחר אז הטest שלי עובר למרות שהקוד בכך עובד אז מה שאני רוצה זה לבדוק שמשהו [\[13:39\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=819s) ששורה מסוימת זורקת אספtion אז גם אם יש את הפtion אל תשתמשו בו אז כי זה API שלךשן הנה API קצת יותר חדש עושים assert throws ty של exception ופה נותנים delegate זה עוד דרך אגב contrול shift space נותן לך אפשרויות מה איך למלא את הפרמטר רואים ואז נורא נורא קל לעשות דברים אומר תשמע אתה יכול לשלוח פה פונקציה או ליצור פונקציה חדשה או לשלוח del דלגate או לשלוח למדה [\[14:12\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=852s) למי כבר יצא לעבוד עםטס למי יצא לעבוד עם לדה expressions אוקיי לנדש ה זה דלגט קצת יותר פשוטים מבחינתי מה שאני עושה זה c add 1001 ו2 אני מוחק את השורה הזאת שבת ככה לפעים אם אני עושה את זה אולי קצת יותר קרי ככה אוקיי אז בעצם מה שאני אומר ש יש לי פה דלגט שלא מקבל פרמטרים והבודי שלו זה אחרי החץ השורה הזאת בלבד אמורה לזרוק את האקספtion [\[14:47\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=887s) אז אם מחר השורה הזאת זרוק אקספtion הסט שלי יקשה אבל כל זמן שהשורה הזאת זורקת אפtion הס שלי ימשיך לעבור זה גם פיצ'ר שחסר בnsms test אין עשר למרות ש לא >> מה >> יש בערך >> יש בערך את הספר שזה >> אבל זה לא במסט test ב >> אבל ב-MSTest זה לא בלתי אתה צריך להוריד שמשתמש בו >> כן אבל flוא assur הוא לא בלתי בתוך MSTest fl זה dl שאתה מוריד >> הוא לא ממייקרוסופט [\[15:22\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=922s) הוא לא חלק מmstס אז הוא לא פיצר של mssס זה משהו שאתה מוסיף >> עכשיו אתה גם יכול לכתוב את זה בעצמך לוקח שש שורות של קוד לכתוב משלכם בסופו של דבר זה ממש ממש פשוט מה שלא מסביר את הסיבה למה למייקרוסופט גבר אחרי שלושה רליסים של פשו סטודיות לא הוסיפו את זה אבל זה מסביר על רמת המחויבות שלהם בעולם היו מטestטים על כמה אכפת להם מבחינת ההתקדמות שם זאת אחת הסיבות שמבחינת MSTest היום ממערכת שהיא זה כמוס זה כאילו הE ש של הtest frameס אוקיי יש לו בדיוק מספיק כדי לראות דברים בסיסיים אבל אין לו test cases אין לו pr יש לו עדיין באגים בחלק בחלק מהמקרים הוא הרבה יותר [\[16:03\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=963s) מבחינת הפיצ'רים הבסיסיים של tdd הטestטים שאתם תכתבו עם ms testים יהיו פחות maable פחות readable אל כן תצטרכו להוסיף דברים כמו fltion וכולי שזה dlים וכל מיני הלפרים אבל בלתי בתוך הכלי אין שום דבר מספיק טוב אוקיי שזה מעניין בגלל שהבן אדם שכתב את אין יוני במקור הוא עובד במייקרוסופט עכשיו זאת אומרת מייקרוסופט קנ את הבן אדם ככה שמה אותו שם הוא לא עובד על סטודיו אבל הוא לא עובד על הניטestי גם בVטודיו [\[16:33\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=993s) בהפסנאות שם >> הוא עבד מה באפסנאות אמרת >> שאלה אם אם יש לי בפונקציה add יותר מאקספtion אחד אותו אספש ואיך אני אדע ש >> אם יש לך בפונקציה יותר מטyפ אחד של הפונקציה יכולה לזרוק כמה פעמים >> אה אז יש את multפile resultלs אז כל אחד מהם סניפה נכון כל אחד מהם היא זורקת במקרה אחר >> לא לא >> לא יכול להיות בקספש הנכון מזרק בדיוק >> שהטייפ הנכון של האקספtion או שהמג הנכון אותה זה בערך המרך המ אם יש לך מסage >> אז אז בוא אני אסביר א' אתה אם זה לפי טייפ אז אתה משנה את הטy >> לא ברור אבל אם אותו >> אבל אם הוא אותו טייפ אז אתה יכול לקבל את האפtion ישר כי זה פונקציה אתה יכול לקבל את האפtionקט [\[17:18\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1038s) ואז אתה יכול לעשות עליו x נפל מג יש לך את כל המידע אתה מקבל את obק עצמו כאילו אתה יכול לעשות אסרט אני לא משתמש בסרט הרquול כמעט עלסטרינגים מה שהייתי עושה הייתי עושה אשרט או תראו בדיוק הייתי משתמש באובייקט אחר בני שנקרא string string ואז הייתי נותן לו את expectected נגיד message needle [\[17:50\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1070s) ואת הxנ message והסיבה היא שאם אני משתמש עשר על סטרינגים סטרינגים תחשבו על זה זה סוג של UI יכול להיות להם פתאום את הטיים בהתחלה יכול להיות להם new lינס בסוף לא אכפת לי מהדברים האלה שמשתנים כל הזמן אכפת לי מהcore mage אז הטestט הזה יחזיק הרבה יותר זמן מאשר טestטים שם מודדים שהסטרינג נראה בדיוק ככה מחר אני רוצה להוסיף גם עוד משהו בסטרינגים שלי אבל המסג עדיין צריך להיות אותו דבר אז הטestט הזה ימשיך לעבוד [\[18:22\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1102s) כן זה מתחשב בקייסינג הונט הקט הזה הוא מתחשב בקי >> כלומר >> אז אתה גם יכול להשתמש בגular exp >> אוקיי אז במצב אבל הלוכחים זה היה casing שונה אז זה לא היה עובד >> אם אני לא רואה יש פה את ה את האפשרות לשנות גם את הקיסים אה יש לו זה יש לו strרנ יש פה אני לא זוכר בדיוק אני בדרך כלל משתמש בקייסים וזה לא משנה [\[18:56\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1136s) דווקא קיסינג זה משהו שכן חשוב שמתחיל באותיות גדולות פול זה לא זה לא משהו שפגע בי בעבר אז לא הייתי צריך לגלות את זה אבל זאת לא אמורה להיות בעיה עוד שאלות בכלל כל פעם שאתם רואים אותכם עושים אסרטול עלסטרים תחליףו את זה לסרטס הטestטים שלכם יחזיקו הרבה יותר זמן אוקיי אז זה מבחינת rows יש עוד כמה פיצרים של [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)") שאנחנו צריכים להכיר ולדעת [\[19:27\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1167s) לדוגמה יש עוד אפג שנקרא את הטestים שלנו אתם רואים שיש after אחרי כל test אוקיי עכשיו מה שמעניין זה שהטest הזה נחשב בגלל שהמג' באמת לא מכיל את ה זהו הוא חיל I can't do thatדא [\[20:01\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1201s) הוא קורה אחרי כל test למה לדעתכם אפשר להשתמש בו לנקות את ה משהו חוק רצים רול בפידת >> זה בעצם ההפך של סטאפ ההפך של setטאפ אבל זה יש משהו מאוד מעניין בטרדאון מבחינת הפטר של השימושטרדון אתה משלם כדי לנקות אחריך אם יש לך מה לנקות וזה לא בזיכרון רוב הזיכרון שמה שיש לך זה לא unit test אלא inרation test זה מאוד חשוב צריך לנקות דבס זה לא unit test כבר אתה משתמש בו משתמש בפסיסטם [\[20:40\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1240s) בנתנו un test >> זה הפנט test מכסה רץ בזיכרון הוא קנסטי הוא לא נוגע בdeפendes של fסם database וכולי לכן אני קורא לכל הדברים אחרים [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec3 "Integration tests (The Art of Unit Testing, 2nd ed., ch. 1)") עוד פעם זה חשוב שוב לי לדעת שאני אם אני רואה טרדון אני אומר וואלה 95% מהזמן זה test יש מקרי קצה מסוימים שבהם יש לך סינגלטון statטיק שאתה רוצה לנפות כל מיני הלפרים שאתה רוצה לעשות להם reset שהם בזיכרון זה המקרים היחידים שבהם טד make sense וזה unit test כשזה חשוב כי כשאנחנו נתחיל לעשות testw אחד לשני ונראה את הקוד אחד של השני אז הטרדון האלה מאוד חשובים כי הרבה פעמים זה סימן שמה שיש לך זה אינטגרש test הוא צריך להיות בפרויקט אחר שנקרא mypegration [\[21:25\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1285s) Test אני מפריד ביניהם בגלל שגration tests אני בדרך כלל רוצה להריץ בבילד נפרדים מאשר unit tests הם הרבה יותר איתיים וגם אם אני אם יש לי מיקס ביניהם אז הרבה פעמים integraation tests הם אתה עושה get lest verion של הקוד שלך integraation test בדfaultט הרבה פעמים צריכים קונפיגורציה אז אז הם נופלים אבל מה שאני רוצה זה שיהיה את את האקספרerס הבא מוסגת מריץ את את כל הפרויקט של הטestטים וכולם ירוקים, כולם עוברים. [\[21:59\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1319s) אוקיי? אבל אם פתאום אחד נכשל ואני שואל את ה את ה מי שכתב את הטest למה הטסט הזה נחשב? ואז הוא אומר לי אה זה בסדר, זה פשוט חסר לך פה הקונפיגורציה אז אני מתחיל לא להאמין לטסט שלי, נכון? אני רוצה שכשיש לי הכל ירוק ואחד לכשיו אני רוצה להיות מודעג, אני לא רוצה להגיד אז זה בסדר. לכן אני מפריד ביניהם כי אני יודע שבנגר test שם זה בסדר להגיד זה בסדר חסר לי קונפיגורציה אבל בני test זה אף פעם לא בסדר בIT test get verion תמיד עובר אין דבר כזה שאני עושה getion ויש לי testים שנכשלים בIT testing testים שנכשלים לפעמים כי חסר לי דטפיס כי זהסטרד כי זה רנדומים נשים אותם באנטגרש test ושם אני יודע אני מצפה לזה שלא בכלל כולם יעברו ביולט אבל לפחות יש לי איזה פרויקט אחד או כמה במערכת שהם the save green זור ששם כולם אמורים לעבור ואז יש לי איזשהיא מידה של ביטחון שהמערכת עובדת [\[22:53\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1373s) אוקיי שיר >> מה >> הם אלה שירוץ >> הם גם אלה שירוץ בטוס integration אבל זה גם קשור למהירות יכול להיות לפעמים שאני אריץ test בinusation אם אני יכול כי יכול להיות שיש לי integration test שהם מהירים יחסית אז אז אני מחלק דברים לcration daily build לפי מהירות של הטestי אבל מבחינת החלוקה לפרויקטים זה קשור לא למהירות זה קשור לקונסיסטנטיות שלי אוקיי וזה קשור לעובדה שאם יש לי שליטה או אין לי שליטה בדרך כלל אין לי שליטה על דברים אחרים עלפילסם יש לי בטestטים שבהם כתבתי את הפרויקט שלי יש לי כונן z אבל באינטגרשט test הוא מצפה על כונן אבל בביל סרבר שכחתי עדיין לשים את הכונן הזה וכולי [\[23:41\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1421s) אוקיי עוד דברים שאלות לפני שאתם מתחילים לכתוב סרטון >> חוץ מאלת את הדברים האלה רצים גם מקומפילציה >> לא הבנתי >> חוץ מריץ אותם כאילו ידנית רצים גם >> אוצרקפג משהו האלטר r הרצה של testר הוא עושהס וגם מריץ קומפילציה לפני זה לא צריך לעשות שום דבר אני לא צריך לעשות בילד לא >> אתה רוצה שזה יקרה אוטומטית בקומפילציה טז רבן לא עושה את זה בשביל זה יש כלי אחר שהוא חינמי שנקרא AutoTest.NET [\[24:12\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1452s) זה דף הבא שבכלתי להראות שזה יפה רואים פה את המני הזה לצערי זה לא קיים בנוגד כי זה לא פק זה לא dependency אבל זה פרקט open source יכולים להוריד את הטלר שלו מה שאתם עושים אתם אומרים וואלה resום engine בפרויקט הנוכחי שלכם ואז אני יכול לראות את ה את הפבק וויידו שלי עכשיו כל פעם שאני עושהסיב נגיד אני עושה פה רווח וסיve contrול s משהו שהוא עושה [\[24:44\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1484s) שפה הוא היה אמור לזהות את זה test. Net צריך צריך סטא נראה מה קורה מעניין לא מריץ את זה לפעמים זה מריץ לפעמים זה לא מריץ אנחנו נעבור יש בעיקרון שלושה continוס test frameworks שלושתם חינמים כרגע יש את ה-AutoTest.NET שאני בגדול התחלתי לנסות אותו רק לפני כמה ימים [\[25:14\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1514s) יש את ה-NCrunch אch הוא הוא החזק מביניהם הוא גם יודע לחלק להריז את הטestטים ברקע עםפle thדadס יודע לעשות אגנור לחלק מהטestטים יש לך הרבה טestטים בלגסי אבל הוא הולך להיות מוצר לא חינמי בעתיד אבל כרגע הוא חינמי והוא לא open source ויש את Mighty Moose Mighty Moose הוא הוא גם continuous tests החוזק שלו הוא עלה הכסף ועכשיו הוא חינמי אבל הוא לאסוף החוזק שלו הוא מבוסס על AutoTest.NET אבל החוזק שלו האמיתי זה שהוא גם משתמש ביוריסטיקות [\[25:48\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1548s) כדי להבין איזה טestטים צריך להריץ לקות ששיניתם אז הוא לא מורץ את כל הטestטים אוטומטית יש לך 100 טestטים אבל רק ארבע צריכים לרוץ אז הוא ירץ רק את הארבע האלה הוא משתמש בהמון סוגים של קoverage ופיילינג כדי לעשות את העבודה שלו בגלל זה הוא גם יחסית איתי מאחרים אבל כשיש לכם פרויקטים הרבה legגy test והרבה אנטגרש test הוא ממש ממש מולץ אז גם זה וגם אקרא' מאוד חזקים אני אני בכוונה רציתי לנסות להראות לכם את האוטוטest אבל משום מה זה כמובן בדמוים תמיד הפעם הראשונה שברים עסיקים לעבוד [\[26:21\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1581s) אז יש פתרונות כאלה ואתם יכולים לנסות להתקן אצלכם כל אחד מהדברים האלה כנראה אין קנץ זה את ה קנץ בינתיים אני הכי אהבתי כי הוא יחסית מהיר ואפילו לא צריך לעשות סיף אתה כותב אות והוא כבר מנסה להרץ ברקע מאוד חמוד עוד שאלות אוקיי אמ לא הנה הפרט window של הtestam דרך אגב [\[26:52\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1612s) מעניין אני לא רואה פה את הטestטים אבל לא משנה בסדר מה שנעשה עכשיו ניכנס קצת לTDD ואז אנחנו נלך להוספסת הצהריים ואז נחתוך קצת יש פה איזה משהו ששכחתי אוקיי TTD מורכב משלושה חלקים אם עכשיו כתבנו מטestים עכשיו אנחנו נכנס לtest first בtd יש שלושה חלקים בדרך כלל כל אחד מהם מרגיש יותר מבוחך מהשני כשאתה עושה את זה בפעם הראשונה אבל צריך לזכרו שבתהליך הלמידה הרבה פעמים צריך לעשות משהו בזמן מסוים כדי להבין את הוול שלו [\[27:35\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1655s) אז אם יש משהו אחד שאני מבקש ממכם בשלושה ימים של הקורס הזה לעשות זה להש להישאר עם ראש פתוח ולנסות דברים גם אם אתם מרגישים שהם תקשיים גם אם אתם מרגישים שאתם שאתם חושבים שאתם שזה לא רעיון טוב מבקש ממכם בכל מקרה לעשות את זה להישאר עם ראש פתוח אחד הדברים המעניינים זה שככל שאנחנו עושים את הדבר הזה יותר בדקות בהתחלה כשאנחנו מגיעים לקוד האמיתי לקוד המסובך הצדים האלה שומרים עלינו הרבה יותר זומרת התהליך פה הוא הרבה יותר לעבודה אינקרמנטלית סימפליסיטי [\[28:06\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1686s) כמשהו שקשה לעשות שאם אתה יודע לעשות אותו בדברים הקלים, בדברים המסובכים הוא מאוד עוזר לך. אז בדברים הקלים הוא נראה מכוח. בדברים המסובכים פתאום הוא נראה מאוד מאוד עוזר. אה אז אז אז הדבר הראשון זה make it fail. בtd הפרק מבחינתי הוא read only. אני לא נוגע בשורת קודק בלי test שנחשב. אוקיי? אני יכול לעשות פקטורים אבל אני לא משנה פונקציונליות. אז מה זה מה ההבדל? מה זה פקטורים? מישהו יודע את ההגדרה? [\[28:40\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1720s) רפקטורים זה שינוי קוד בלי שינוי פונקציונליות אוקיי עשיתם רני לפונקציה זה נקראפקטורים לקחתם פונקציה ארוכה וחילקתם אותה לחמש פונקציות קטנות זהרפקטור כל זמן שלא שיניתם מה שהיא עושה אז פקטור זה בדרך כלל שינוי המטבילטי של משהו אז אין לי בעיה לשנות קוד ולעשות פקטורing אבל אני לא הוסיף לו פיצ'רים הוא אשנה פיצ'רים קיימים אני מקסימום אשנה את המבנה של הקוד אז אני מתחיל מטest שנכשל אני גורם לטסט לעבור בלי לגעת בטestט. הרבה פעמים אנשים אומרים הטestט נכשל ואז אני משנה את הטestט ואז הוא עובר. [\[29:13\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1753s) אבל המטרה היא לשנות את הטest כי הטest הוא ההגדרה שלך למה זה ההצלחה. Define success. אז successס זה שאני יכול לעשות ככה וככה. עכשיו לגרום לט לעבור זה to achieve success. לגרום לproductiontion c לעבוד כדי שהטest יעבור. אבל הקט האמיתי הוא שהproduודקש קוד עובד נגרום לו לעבוד בצורה הפשוטה ביותר. הפשטות זה החלק הכי מסובך בדרך כלל בקורס הזה כי המוח שלנו הוא מכוון לעבודה מאוד מאוד גנרית לעבודה מאוד [\[29:46\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1786s) שעם המון שמורידה את כל הספש שלנו לגבי הקודמה אנחנו נכתוב קוד שיודע לקבל את כל הסוגי האבוד אבל פה אנחנו נוריד את זה אנחנו נדע את זה סוגי אינבות וזה מה שמוביל בין השר לעבודה אינקרמנטלית הרבה פעמים אנחנו מנסים להתחיל לעשות פיצ'ר ואז לוקח לנו שבוע מהפיצ'ר לעבוד אבל היום אנחנו יכולים לעשות פיצ'ר בחלקים קטנים שכל אחד מהם עושה הרבה הנחות יסוד ואז לאט לאט מורידים הנחת יסוד אחת אחרי השנייה דוגמה כמות האינפוטים סוגי האינפוטים אז valing valid val כל אחד מהם הוא פיצר בפני עצמו ואז כל הזמן יש לי משהו שעובד אבל הוא עובד קצת יותר ג'נריק קצת יותר ג'נריק אבל אני מתחיל ממשהו מאוד לא ג'נרי מאוד גנרי [\[30:29\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1829s) אז כשיש לי את הטest עובר אז אני עושה ריפקטור זאת אומרת אני משנה את הפונקציונליות גם בטestטים וגם בפרדtion. אם אני רק משנה prodctiontion ולא משנה testים אז הטestטים שלי יהיו unreable וmainable. תזכירו גם בטestטים את הרפקטורing אני עושה רק אחרי שהטestטים עוברים בגלל שהמטרה שלי לגרום לפונקציונליות תקיים. אוקיי אז make it better זהctטורing אם אני לא עושה את השלב של הריפקטורing אז הרבה פעמים הסימפליסityי מוביל לקוד מאוד מכוער [\[31:00\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1860s) ואם אני אשאר עם הקוד המכואר הזה אני לא אהיה מרוצה מהתוצאה למרות שהיא עובדת אבל החלק היפה הוא שכשיש לך טestטים ואתה רואה קוד מכוער אתה יכול לשנות אותו יך לעשות אורי פקטורים כשאין לך טestטים ואתה רואה קוד מכוער אתה עושה קופי פיסט ומוסיף את הפיצ'ר בקוד החדש אחרי זה הקודם גם נראה אוקיי, אז תכף נדבר על simplity. א, בואו עכשיו נוסיף פיצ'רים לקלטור. א, אבל הפיצ'רים שאני אכניס הם [\[31:33\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1893s) כן, בואו נתחיל. יש לכם איזה רעיון להכניס לפיצר לקלט שלנו? >> מה? >> זה מתמטי. אני רוצה משהו עם לוגיקה משהו שחנו להוסיף לוגיקה לא ייתן לנו לחלק באפסנו לחלק value זה גם ככה המערכתומכת בזה אסור value מה זה לשמור לשמור ערך כדי להשתמש בו מחר כחול פה >> לשמור אה זאת אומרת שיהיה לו ממורי כן >> אוקיי [\[32:06\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1926s) אז אם אנחנו רוצים להוסיף את הפיצ'ר הזה הדבר האחרון שאנחנו נעשה עושה זה ללכת לפקש פה אני לא מוסיף את הפיצ'ר קודם כל אני כותב טest לדבר הזה אז עכשיו אני רוצה לכתוב את הפיצ'ר אז בואו נתחיל מאיזשהו טestט חדש קודם כל אני מתחיל בטest אז מה המרשפ של הפיצ'רמור >> mורי סצנריו מה מה הסנריו יכול להיות שיש לי הרבה סנר לקלות פה מה הסנריו הכי פשוט לעשות ממור [\[32:44\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1964s) סט וג אני אם יש set וגט אז מה הכי פשוט ביניהם? >> לאג יש לו דפלט נכון מסכימים איתי? לכל דבר שאתה יכול לעשות עושה יש לו גט ולכן תמיד הגט הוא הראשון ככ כי הטestט הכי פשוט זה טסט שעוד לא עשית גט נכוןס שעוד לא עושים את הסט אוקיי בסדר mורy אז אם אנחנו עושים get set אז אנחנו יכולים פשוט לעשות אפט default defaultט [\[33:14\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=1994s) מה הדיפולט שלו >> מה כפת אתם defult mורy >> לכתוב mורy by default אבל מה בוא בואו נחשוב מה הב מה הבי של ממורי אז זה הפיצר שלך מה אתה הפרודקט אומר שלך >> אפשר לו לשים לו תוצאה כלשהי >> תוצאה כלשהי אבל הוא לא עשים לו תוצאה זה הטסט הכי פשוט שהוא הוא מחזיר ל מה שיש לו איזשהו אם ש אין לו אפס אחלה returnsים [\[33:46\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=2026s) להגיד שזה returns default value במקרה שלנו אני בכוונה נפשט את זה ואני אגיד return zero כי במemורy default של מרטג תמיד 0 אוקיי make אטריזל שווה c איך נקרא לה פונקציה get mורy או סתם mורy propפרery זה לא משנה אבל זה כן משנה איך היית רוצה מה ה היה מושלם [\[34:18\]](https://www.youtube.com/watch?v=_BrBkzT-25U&t=2058s) מה >> getג value get sl >> לא צח אבל get כא כיס value ומה הסרט שלנו יהיה אקול אפס ורס נכון מקובל עליכם הטestט הזה אחלה עכשיו תשימו לב אני קודם כל מסיים את ‏test ## Related - [Refactoring to parameterized tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec5) · The Art of Unit Testing, 2nd ed., ch. 2 Refactoring to parameterized tests in NUnit, the same merging of similar tests the lesson does with TestCase. - [Checking for expected thrown errors](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2) · The Art of Unit Testing, 3rd ed., ch. 2 Book section on checking for expected thrown errors, the exception-testing options the lesson compares. - [More NUnit attributes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6) · The Art of Unit Testing, 2nd ed., ch. 2 Covers more NUnit attributes, a natural follow-up to the attribute-based setup, teardown and exception tests shown here. - [Another Entlib example: Separate integration tests from unit tests (and learn to know the difference)](https://osherove.com/blog/2005/4/11/another-entlib-example-separate-integration-tests-from-unit.html) · osherove.com Argues for separating integration tests from unit tests, as the lesson does when a TearDown signals an integration test. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Setting up and tearing down](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_171), ch. 9 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 #### The Art of Unit Testing, 2nd ed. - [First steps with NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3), ch. 2 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6), ch. 1 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec3), ch. 1 [Previous lesson Test Demo](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/test-demo/) [Next lesson TDD Demo](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/tdd-demo/) --- title: "TDD Demo" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/tdd-demo.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/tdd-demo/" tags: [] author: "Roy Osherove" description: "Lesson 5 of 22 in TDD in .NET in Hebrew (Day1 - Unit Testing and TDD 101), 19:26. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # TDD Demo 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day1 - Unit Testing and TDD 101 Lesson 5 of 22 Duration: 19:26 [Watch on YouTube](https://www.youtube.com/watch?v=DK7lVa2Sz94) Spoken in Hebrew ## In this lesson Roy Osherove builds the calculator's memory feature with [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)"): first a failing test, then the [simplest code](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") that passes all tests, which he describes as code with as many assumptions as possible, near the top of the function and with few ifs. The group designs the API through the tests, and he writes future tests down as comments so there is one problem to solve at a time. He also answers questions on organizing many tests, [given/when/then](https://osherove.com/blog/2008/10/4/bdd-behavior-vs-spec-frameworks.html "BDD: Behavior vs. Spec Frameworks (osherove.com)") in behavior driven development, and [setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162 "Avoid setup methods (The Art of Unit Testing, 3rd ed., ch. 8)"). ## Transcript 2,897 words [\[00:02\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=2s) כי עד שאני לא מסים את הטest אני לא יודע אם זה באמת מה שאני רוצה עכשיו נשאל את השאלה this is my definition of success שבו על זה ככה sucessס מבחינתי זה היכולת לעשות את הדבר הזה עכשיו אני גורם לעולם להתאים את עצמו אליי אוקיי סוג של משחקת אלוהים פה אז אני גרם לזה להתקמפל אבל אני חייב לראות את הטסט נחשב אוקיי לא מתקמפל זה כביכול סוג של כישלון אבל עדיין לא אבל לא הצלחתי עדיין להריץ אותו אז אני רוצה את היכולת להריץ אותו ולראות את הטest זה החוק הראשון בD [\[00:33\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=33s) אז alt enter כדי לייצר את הפרטי הזה מה שהתכוונתי en public הוא בא לי אחרי זה אם אני רוצה לעשות איזהסט אחרי זה אני אשנה את זה כרגע testing possibly work הבעיה היא שאם אני ארץ עכשיו את הטסט הזה יהיה אפס בדפ נכון אני בכוונה רוצה לראות אותו נכשל אז אני אתחיל אותו [\[01:05\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=65s) למינוס אח אוקיי תזכרו החוק הראשון זה לראות את הטestטב עכשיו אני רוצה שזה ירגיש כמו בט דרך אגב הטest הזה של האספtion אני יכול להגיד can't כדי שהחסד זה יבוא שומע ממשיך קשה >> קטנה >> יפה מצוין אוקיי אוקיי, עכשיו יש לנו את האפטר. בוא נוריד את האפטר שלא יהיה לנו ברש אתר. אוקיי, עכשיו יש לי בעצם [\[01:38\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=98s) הגעתי, עברתי את השלב הראשון בTVD שזה לראות את הטest הראשון נכשל. בהתחלה הפונקציה עוד לא הייתה קיימת, גרמתי להתקיים. expected אפס 1. עכשיו אני יכול לעבור לשלב ה לשלב השני זה לגרום לכל הטestטים לעבור בצורה הפשוטה ביותר. עכשיו בוא נחזור לסימפליסityי. אז מבחינתנו simpliסityי זה אפשר לחשוב על זה בכמה דרכים אבל זה קוד שעושה כמה שיותר הסט כמה שיותר הנחות יסוד [\[02:10\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=130s) זה הקוד הכי פחות ג'נרי שאתם יכולים לחשוב עליו וינתן הרצון להעביר את כל הטestטים אוקיי אז אם אתם יכולים לעבור את כל הטestטים אבל יש עוד הנחת שאתם יכולים לעשות שתפשט את הקוד יותר אז תעשו את זה אז איך נראה הקוד פשוט בדרך כלל יותר קרוב לתחילת הפונקציה ככל שהוא יותר נמוך בפונקציה הוא צריך לעבור שורות קוד לפני זה אז הוא פחות אז הוא יותר מסובך נכון אם הקוד אם הייתי צריך לעבור כמה אייפים בדרך אז הקוד יותר מסובך מאשר אם לא הייתי צריך לעשות כלום אז קוד יותר קרול לתחילת הפונקציה ויזואלית אז שורת בדרך כלל תהיה יותר קצרה אלא אם כן הוא בלתי קרי אז אני רוצה שהוא יהיה גם כרי והוא לאנטל כי אז בדרך כלל זה אומר שיש אי אופ או משהו בסגות אז זה קוד שככל שיותר הוא קרוב לx0 וy0 [\[02:54\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=174s) יותר טוב לי אז אם אני יכול לכתוב פתרון לטסט הזה בתחילת פונקציה כלשהי זה הרבה יותר טוב מאשר לכתוב את זה בסוף פונקציה כלשהי ואם אני יכול לכתוב את זה בלי איפים אני אכתוב את זה בלי אפים זה ככה אני חושב על סימפליסיטי כי לא הצלחתי למצוא דרך אחרת לחשוב על סימפליסיטי זה יכול להיות לא מושלם אבל לא מצאתי דרך יותר טובה לפחות לחשוב על זה למדוד אם אתה כותב משהו שהוא פשוט אמ אוקיי אז אנחנו בפרודקש קודז כרנו יש לנו test אחד שנכשל [\[03:28\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=208s) זה הטest הזה stort value אני כרגע יכול לשים את הסטור value כאפס זה הדבר הכי פשוט שאני יכול לחשוב עליו ואני יכול לעשות אפילו פשוט ככה עניין על ה כל הטestטים עוברים מצוין הפיצ'ר עובר אפשר הביתה מצוין יופי כל אחת יש סינריות >> שייכת הביתה או לא >> סנריות לא מי סתם פונקציות לאסט יופי אוקי א' הפונקציונות נעסתה בחלקה חסרים טסים >> נכון אבל תשימו לב הפונקציונות נעסתה בחלקה יש לי פיצ'ר שעובד בעינתן שלא השתמשת בממור את מסכים איתי [\[04:07\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=247s) אינקרמנטלי זה אינקרמנטלי זה לא חייב להרגיש מדהים אבל זה עדיין עובד חלקית אוקיי אז עכשיו אם הפיצ'ר הזה אם אתם לא מרוצים מהקוד הזה מן הסתם הקוד הזה לא מספיק טוב אפשר לשנות אותו נכון לא אי אפשר לשנות אותו נכון כי בtd ‏D יכול לשנות קוד אם אין לך טסט שנחשב. אז אם אתם באמת אכפת לכם מהקוד הזה אתם רוצים לשנות אותו אתם צריכים לכתוב טest חדש שנחשב. כל הטסטים שלנו כרגע לצערינו עוברים אז כדי לשנות את זה אנחנו צריכים לכתוב טסט חדש שנקשר. [\[04:39\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=279s) מה הטestט שנכתוב? גט. בואו נעשה את זה ככה. Test memורי. מה נעשה עכשיו בסנרים? Setט. >> אוקיי. הסנריו הכי פשוט שמוכיח שהקוד לא בסדר כן >> גט setסט ואז ג >> set יותר פשוט כ >> אם אני סתם עשה גט אני עדיין אקבל אפס נכון אז אני צריך את שנכשל set >> set אוקייס set ומה הבי במקרה כזהס [\[05:14\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=314s) >> מה זהסק >> שימו לב רגע איזה איזה סוג של resultלצר retire value state אוס >> partטy state >> בסטate איך בודקים שסטate נשתנה עושים גט אוקי >> עושים גט זאת אומרת ההתנהגות של המערכת משתנה לא בודקיםסיטל אלא בודקים איזשהו פאבליק API שמחזיר איזשהו תוצאה אחרת אוקיי אז set אבל כשאם ה חזיר תוצאה אחרת מה זה אומר על ההתנהגות שלו שמemמורי שהvue is save נכון או משהו בסגנון הזה [\[05:45\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=345s) Value save to mory אוקיי אז אני יכול להגיד ככה לא cort value שווה נכון זה מה שאתם רוצים שאני אעשה >> כן >> אחד >> שווה 1 אחלה [\[06:18\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=378s) 1 מCסטור value כבר גט >> אז מה מה המטרה של הפיצ'ר הזה אני רוצה להבין >> זה שסתם עכשיו יש לי פילד שאני יכול לתוסט לזה אין לי מה לכות >> אם זה לא היה פילד היה פונקציה שמחורי הקלים אני עושה כל המסובות >> זהו אבל מה אכפת לי אם היא עושה את זה מאחורי הקלים מה איך זה משנה את ההתנהגות של המערכת שלי מה זאת אומרת יש לה משהו שומר ברקע אחד באותה מידה אחר כך שמשפילו של >> יפה אז זה מה שחשוב לי שאני יכול לעשות משהו עם הסט הזה זה שאני סתם לחסט לא שווה לי שום דבר אוקיי אז אם אני עושה לו סטור שווה ככה [\[06:56\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=416s) אז יכול להיות שהדפט test שלי לא נכון יכול להיות שהדולט שלי היה צריך להיות שאני משתמש בדפולט זה כמו להשתמש באפס נכון ב1 בוד 1 אז גם את זה יכול לעשות test >> בוא נעשה את זה ככה אז איך אנחנו נשתמש בסטור value שלנו בiס פונקציה multפלי בסור value mtiply בסור value >> לא שהad שיהיה גם add שמוסיף לסור value האחרון ושגם add רגיל משנה אתסורה לי c [\[07:26\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=446s) To to st value >> כן >> ככה >> וזה יחזיר לי תוצאה >> כמו >> פלמטר אחד >> זה מה שהתכוונת שיני >> זה גם אפשר כאילו >> חשוב שתבינו מה אנחנו עושים פה עכשיו אנחנו עושים פה את הדיזיין של של הפיצ'ר אוקיי >> כן >> זה החלטה שלכם איך הפיצ'ר הזה יראה אז אני שואל אתכם איך הפיצ'ר של ממורין נראה בטיפטר שלנו זה כל דבר שאנחנו נעשה יש שנה את הפיצא שיש פה רק דרך אחת אין דרך אחת יש את הדרך שבא אתם מאמינים שהp צריך להשתמש בו >> יכול לגרום לזה לעבוד >> מה [\[08:00\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=480s) שהד מתחיל מהסטור משתמש פהסטור >> אוקיי אז יהיה לי add אה זאת אומרת שad אוטומטית כבר יחזיר משהו אז יהיה לי 1 ו שתיים ואני אקבל ארבע אוקיי זה כבר התנהגות יפה in resultלט [\[08:31\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=511s) אר אוקיי עכשיו יש לנו לאן לשאוף אז שימו לב הפיצ'ר הוא קטן יש לי מטרה לשאוף אליה אני יודע כשאני אצליח אותה שתצלי יעבור ואז אני ארגיש טוב עם עצמי להרגיש טוב עם עצמך זה דבר מאוד חשוב במעלה היום אני לא יודע אם איך להגיד לכם את זה פסיכולוגית כשהיום שלי מורכב מהרבה טestטים קטנים שעוברים אז היום שלי מורכב מהרבה הצלחות עדיף מאשר שהיום שלי מורכב מפיצ'ר אחד שלא עבד כל היום ואז אולי מחר הוא יעבוד ואולי לא עבודה אינטרמנטלית זה משהו שאמור להיות כיף גם יש מצב שמישהו אחד כותב הטסט ממישהו אחר מממש את זה [\[09:02\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=542s) כי זה נגיד לא הכי קרי זה לא לא לגמרי ברור >> בוא נעשה את זה קרי איך היית עושה את זה קר >> משנה את השם של add ל using st value add using store value זאת אומרת את הפונקציה המקורית תמיד יקרה addingסטור value יש פה כאילו שכל מסייסף את הסט נכון זה הנחה ש בדרך כלל לא נכון והתנהגות שלפ >> אבל זה מה שאנחנו כתבנו פה בסדר מחשב שמצאנו שהוא >> אבל מה אם הייתי כותב פה [\[09:34\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=574s) C use stored value in addווה true או זה יותר קרי עכשיו נגרום לזה למה אפשר אפשר אפשר זה אחד הדברים היפים הטestטים שלנו הם עוד יוזר של המערכת אז אם הAPI לא מספיק נוח הו אז אנחנו רואים את זה בזמן שאנחנו קובעים את הטestט ומכיוון שהPI עוד לא עובד ועוד לא קיים אז העלות שיבוא שלו היא מסערית [\[10:15\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=615s) אוקיי אז בואו נעשה נעשה את הפיל הזה אני בכוונה עושה את זה פיל הוא יותר פשוט מפורתי עד R. מצוין. יופי. אז אם עכשיו זה משהו יותר קרי אז גרמנו הטest לרוץ ולהיקשל. עכשיו אנחנו צריכים ללכת לקוד שלנו ובצורה הפשוטה ביותר לגרום לכל הטestטים לעבור. תזכרו לעשות כמה שיותר הנחות יסוד. אז מה הדבר הכי פשוט שאפשר לעשות? לבדוק אם הטרו ואם כן אז להוסיף. [\[10:47\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=647s) >> לבדוק אם הותרו ואם כן אז להוסיף. >> רק להוסיף. רק להוסיף. אין לנו שום טestט אחר שבודק שאם שאם זהפלס אז זה לא מוסיף נכון >> בגלל שהדפולט שלו הוא אפס >> נכון אז אם אני יכול לעשות את זה וכל הטסטינג זה מצוין לי אבל לא אני הולך להשתמש בפט צריך להוסיף לו טסד defultט אפס בכל הטסטים האחרים אז אני אפילו לא צריך לבדוק את הפולס >> צריך להוסיף לו טestטים שתקו אתה >> אני מצטרך להוסיף כי החוד הזה לא יהיה מספיק טוב >> אבל זה כל הרעיון של עבודה אינקרמנטלית אם אני יכול לעשות את הספle gear אז אז אני מכריח את עצמי לכתוב את הטסטים הבא [\[11:22\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=682s) שאולי אחר כך לא היה לי צריך לכתוב אותם כי הייתי מרגיש שהקוד כבר עובד בצורה מושלמת הבעיה הרבה פעמים טסטים שאתה כותב אחרי אתה אומר אבל הקוד הזה כבר עובד אני יכול לכתוב פיצ'ר חדש או סתם לכתוב טסטים שגם ככה יעברו אני יודע שהם יעברו אבל אם אתה מתייחס לזה כבג כי הטסטים באמת לא קיימים הפונקציה לא קיימת או פונקציונליות לא קיימת אז אתה מוכח את עצמך גם לכתוב את הטסטים האלה שמתעדים את הפונקציונליות פלוס st בוא נראה [\[11:53\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=713s) דם אוקיי זה באמת היה פשוט אז כרגע יש לנו פיצר שעובד חלקית שזה עבודה עם סטור יכול להיות שיש לו בגט שהוא לא שאני לא יכול לכבות אותו בי defaultט אבל הוא עובד חלקית אני כרגע יכול לעשות אפילו דליבר לדבר הזה כן >> אני מרגיש שכשאתה עושה את זה ככה בצורה כזאת אז בעצם אתה צריך לזכור שאמנם הטסטים עוברים אבל יש איזה סנריו מאוד ספציפי למשל הסנריו שבו stדו הוא פלס כן >> ש שלא ש שלא חשבת על שאתה לא צריך לכתוב לו טestטים נכון >> אז זה לא יותר פשוט אתה יודע מראש מה אתה רוצה שיקרה אז תכתוב את כל הטestטים תחסה את כל המקרים ש זה מסודר לך בראש אתה יודע מה כל מקרה צריך לעשות הם כולם יקשלו ואז ואז תכתוב את המימוש למה לא לעשות את זה ככה [\[12:36\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=756s) >> שאלה מצוינת יש לי אפילו סלייד על הדבר הזה זה אומר שזה סילה ממש טובה אם יש לי סלייד מוכן לדבר הזה אני לא כותב את כל הטסטים מראש אני כותב לי קומנטים על טestטים שאני לא רוצה רוצה לשכוח והסיבה היא שאני רוצה שכל פעם יהיה לי רק דבר אחד לפתור כי אני רוצה להתמקד בפתרון הבעיה הכי פשוט אם יש לי עכשיו 20 טסטים לפתור אני הולך לתוף את הקוד הכי ג'נרי בעולם עכשיו ואז יכול להיות מאוד להיות שאני גם אכתוב פיצ'רים שהם לא נבדקו בקוד ג'נרינ הכל יכול לקרות אם אני עושה את הדברים אחד אחרי השני על הסיכוי שאני אכניס לו שם פיצ'ר שלא נבדק הוא מאוד נמוך ככה אני מוודא לא רק שלא חסרים מטestטים אלא שאני לא אכתוב קוד כל כך הג'נרי שלא רק שה-20 טסים שכתבתי עוברים יש גם עוד 40 טסטים שיכולתי לכתוב לדבר הזה אבל למי יש כוח משתויות האלה מבין את הנדנט הקוד שלי יהיה הרבה יותר מסובך אם יש לי בעיה גדולה לפתור ש אם יש לי בעיה קטנה לפתור ואז בעיה קטנה לפתור ואז בעיה קטנה לפתור הרבה פעמים הקוד יוצא יותר פשוט ממה שחשבנו שהוא יצא וזה אחד הדברים היפים שקורה עבודה אינקרמנטלית יכולה להוביל לקוד הרבה יותר פשוט ממה שאנחנו חושבים [\[13:37\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=817s) שהוא יכול להיות וגם אני לא רוצה לסבלות היום בהגשה שאני לא מצליח לעשות משהו חי לרות היום בהצלחה שאני מצליח הרבה דברים קטנים אוקיי אז אז בגלל זה אני כותב את זה בקומנטים לא חייב להיות אוקיי לא שכנע אין לי לא צריך לשכנע אותך זה עניין של איזשהו משהו שצריך להרגיש בגלל זה הרבה מהקורס הזה הוא קידוד ועבודה אינקרמנטלית עכשיו זה לא אומר שהטestטים האלה לא יעשו אבל אני רוצה לוודא שכשאני עושה אותם אני עושה רק אותם אני עושה רק את מה שצריך לדוגמה [\[14:07\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=847s) ה handלciס מחר אוקיי עכשיו אני לא עובד עם דסמלס בכלל נכון אה אנדל יופי ‏and doubles הפצ'רים או testים שלא חשבתי עליהם מה קורה עם נגטiveסimal מה קורה עם דברים אחרים אז אני אכתוב לי בקמנטים את הדברים האלה ואחרי זה אני אמלא אותם אבל אני אחד אחד ואז בכל שלב יש לי משהו שעובד יש לי עוד בראש איזשהו בקלוק קטן שאני עובד בסדר אם יש לי 20 טסים שנכשלים [\[14:38\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=878s) אני כל הזמן רואה אותם כל הזמן רואה אותם אומרים לי אתה לא מספיק טוב אתה לא מספיק טוב וככה אני יודע שיש לי מטרות קטנות וקצרות אני לא אשאל לך את זה. בסדר? אוקיי. אז הפיצ'ר שלנו עובר אבל חלקית אנחנו בכלל לא בודקים אם הפג תחשבו על זה עכשיו. עכשיו זה בעצם באג. אין לי שום בעיה לשחזר את הבאג הזה. אני יכול להגיד אה יש לך סטורד ממור אבל אתה לא אמור להשתמש בו. [\[15:09\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=909s) ואז אני אחזוב את הטest הזה והטסט הזה יתקשר ואז אני אוסיף את האיף הזה בצורה הכי פשוטה ואז נמשיך הלאה. ככה הייתי עובד על זה בינתיים זה אפילו לא פרerטי למה אני צריך שזה יהיה propפרerטy propפרטי בדרך כלל זה כשיש לך לוגיקה בפנים בינתיים אין לנו שום לוגיקה בפנים נכון אז זה שחשבתם שזה יהיה propפרerטי זה לא אומר שזה יהיה propפרטי וז נושא של simpפליסityי מאוד מאוד עובד פה אוקיי הנושא שהנחות יסוד שלכם הרבה פעמים לגבי איך שאתם ממשו את הפוד מה שבאמת קורה כשמגיע הזמן לממש משהו בצורה הכי פשוטה [\[15:41\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=941s) הם הם יכולות להיות מאוד מאוד שונות לנושא של לעשות דברים בצורה כלה פשוטה משנה משנה מאוד הרבה פעמים את הדיזיין שלנו ב עכשיו זה לא אומר שהדיזיין שלנו יהיה מושלם בגלל הדבר הזה וtd זאת לא הדרך היחידה לעשות דיזיין אני מאמין שדיזינר גרוע לא משנה אם הוא יעשה TTD או לא יצא לו דיזיין גרוע אוקיי זאת אומרת אם אתם לא יודעים דיזיין זה לא משנה כמה [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6 "Test-driven development (The Art of Unit Testing, 2nd ed., ch. 1)") תעשו הקוד שלכם בסוף יהיה איכשהו לא נוח לא לא נעים לא כיף לראות אותו גם אם הוא יהיה הכי טסטable שבעולם [\[16:12\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=972s) דיזיין זה מלאכה שלומדים בנפרד ויש ספרים על זה ויש קורסים על זה אנקל גוב יש לו כל רוברט מטין יש לו כמה ספרים יפים על קleן קורד אני ממליץ בחום עוד שאלות שלvידd יש לי משהו לעשות פה ריפאקטורי שאלה לגבי ארכיטקטורה כן >> זאת אומרת עכשיו הוספנו פיצ'ר חדש שרון >> ואתה כרגע כותב את כל הטestטים [\[16:42\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=1002s) בקלאס אחד >> יהיו אלפי טestט קייסים למחשבון יהיו אלפי טestטים >> מאוד אוקיי >> אוקיי >> יכול להיות >> שאלה איך איך לארגן את זה בצורה נכונה זה די מאורגן תשים לב אם אני מסתכל פה זה כבר מסודר לי לפי פיצ'רים זאת אומרת בגלל הניing convention כל הדברים של נמצאים אחד ליד השני אז יחסית קל לי למצוא את הדברים האלה בגלל name לפעמים וזה קורה מאוד להתים רחוקות אני מפריד את זה גם קלאס פרונקציה או קלאס פרat זה גם בסדר לעשות כל זמן שקל לי למצוא את זה אז זה לא לא צריך להיות דתי בנושא הזה זה רק איזשהו משהו להתחיל איתו בפריים התחלתי שאתם לא בטוחים מה לעשות תשתמשו בזה כשתמצאו משהו יותר טוב תמשו במשהו הזה גם בסדר היום בBDD בפריורקים אחרים יש גם את הנושא של לשים nameספי ולשים דברים שהם nested ונסד clesס אבל בסופו של דבר שלושת חלקי המידע מה אתה בודק [\[17:43\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=1063s) באיזה סנר ומה אפ תמיד קיימים אוקיי רק שלפעמים קיימים מקומות שונים ברמת הקס ברמת הנס ברמת הפונקציה then מישהו שמע פעם את הדבר הזה given when then given when then זה כשאנשים רואים [behavior driven development](https://osherove.com/blog/2008/10/4/bdd-behavior-vs-spec-frameworks.html "BDD: Behavior vs. Spec Frameworks (osherove.com)") שזה סוג של אבולוציה של לאן TDD מגיע אחר כך זה TDD יותר קרי תחשבו על זה או משהו שאתה יכול לעשות גם קצת יותר עם הלקוח מתמשגן זה סנר [\[18:13\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=1093s) זה גם זה סוג של act זה behav זה גם הפ שאתה בודק השלושה חלקים האלה גם קיימים במתודולוגיות האחרות אחרי שכבר יהיה לכם ניסיון יהיה לכם יותר קל להתחיל להחליט במה לעבוד זה לא משנה איפה השלושת החלקים האלה כתובים כל זמן שיש לכם אותם הקרירות משתנה מאוד כשיש לכם אז אם אתה רוצה לחלק את זה לקס אחר אין בעיה כל זמן שאתה לא מאבד לי את המידע הזאת >> עדיין אני רוצה אבל שיקריא הסטאפיר דאם אני יש יש פה setup יותר >> כרגע לא >> בדרך כלל דינ בדרך כלל דינ גם בטסטים המסובכים גם כשתמש במק objects setup זה לא כבר רעיון טוב למקובקס גם כי הרבה פעמים משתמשים בהם רק בחלק מהטestי ואז אתה צריך לקרוא את הטestי ואתה חושב שמה שיש בסטנטאפ כולם משתמשים בו ורק חלק משתמשים בו זה כמעט אף פעם לא רוב להשתמש בסטאפ באינטגרש test זה כבר מתחיל להיות רון מעניין אתה רוצה להבי דטב סו דברים כאלה אבל ביני testingים כמעט אף פעם אתה לא תצטרך יהיה לך factטורy methods ובדרך כלל הטest עצמו הואסטקט. [\[19:15\]](https://www.youtube.com/watch?v=DK7lVa2Sz94&t=1155s) בסדר? עוד שאלות. הפסקת צהריים מי מעוניין? אוקיי, הפסקה. אה, כמה זמן הפסקה? חצי ש ## Related - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) · osherove.com Four questions for writing the simplest thing that could possibly work, the passing-code rule the lesson applies. - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6) · The Art of Unit Testing, 2nd ed., ch. 1 Book section on test-driven development: failing test first, then code to pass, as in the memory feature demo. - [The three core skills of successful TDD](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec7) · The Art of Unit Testing, 2nd ed., ch. 1 Covers the three core skills of successful TDD, useful context after watching a first full TDD cycle. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [Avoid setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162), ch. 8 #### osherove.com - [BDD: Behavior vs. Spec Frameworks](https://osherove.com/blog/2008/10/4/bdd-behavior-vs-spec-frameworks.html) [Previous lesson Test Cases, String Asserts and more](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/test-cases-string-asserts-and-more/) [Next lesson Summary Day 1](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/summary-day-1/) --- title: "Summary Day 1" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/summary-day-1.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/summary-day-1/" tags: [] author: "Roy Osherove" description: "Lesson 6 of 22 in TDD in .NET in Hebrew (Day1 - Unit Testing and TDD 101), 8:45. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Summary Day 1 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day1 - Unit Testing and TDD 101 Lesson 6 of 22 Duration: 8:45 [Watch on YouTube](https://www.youtube.com/watch?v=yLBhRenZBeA) Spoken in Hebrew ## In this lesson Roy Osherove notes that by the end of the first day most participants were writing the test first and arguing about implementation, design and [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)") rather than whether to test at all. He previews the second day: replacing the console earlier was a kind of [mock object](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)"), the difference between a mock (which the test asserts against, [one per test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec5 "One mock per test (The Art of Unit Testing, 2nd ed., ch. 4)")) and a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") (any number per test), and frameworks such as [NSubstitute](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html "FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition? (osherove.com)"). He asks everyone to redo the [string calculator exercise](https://osherove.com/tdd-kata-1 "TDD Kata 1 - String Calculator (osherove.com)") from scratch for ten to fifteen minutes every morning so they do not forget what they learned. ## Transcript 1,260 words [\[00:04\]](https://www.youtube.com/watch?v=yLBhRenZBeA&t=4s) חסרים לי עוד אנשים >> לא נורא לא הרבה אוקיי שאלות על דברים שעשינו היום אוקיי אני אני מקווה שהתחלתם לשים לב שרוב הזמן כבר כתבתם את הטסט קודם וכבר לא היה אכפת לכם מישהו הרגיש את הנושא הזה שזה כבר לא משנה שכותבים את הטestט קודם שזה פשוט הדרך לכתוב את זה וזה כבר it's not a וזה מה שרציתי שתחילו קצת להרגיש שהמטרה של הטestטים זה ליצור פונקציונליות חדשה הטestטים אחרי זה נותנים רשת ביטחון ופתאום מגלים בעגים ואפשר לבד שלא שברת כלום אבל ה המוזרות הזאת שחשבים בהתחלה שתחילו את הטestן ולפעמים שוכחים זה משהו שבדרך כלל מתחיל לעבור ביום הראשון ביום השני אבל עדיין אתם בסך הכל עושים את זה אולי חמש שעות אולי ארבע וחצי שעות זה בסדר אם עדיין אתם חלקי חכם עדיין מרגישים לא בנוח עם הדבר הזה אבל אני שמתי לב שלקראת הסוף עיקר הדיבורים היו דווקא על סוגי מימוש ועל הדיזיין שנוצר מהדברים האלה ועלביליטי [\[01:04\]](https://www.youtube.com/watch?v=yLBhRenZBeA&t=64s) והרבה פחות על כדאי לי לבדוק את זה או לא כדאי לי לבדוק את זה כבר היה על דברים הרבה יותר ממשיים כמו איך כדאי לי לבדוק את זה שווה לי לכתוב את הסרט ככה איך הטestט יותר קרי או פחות קרי ובכלל אם יש איזה או איך לעשות ריפאקטורים לקוד וזה סוג הדיונים שמאוד חשוב שיהיה וזה סוג הדיונים דרך אגב שאני מאוד מקווה שיהיה לכם גם בהמשך הנושא של הקוד במהלך הלימוד של הטestטים מאוד מאוד חשוב כי הרדבילי זה אחד הדברים שנורא נורא קל לשכוח ממנו אז אפילו טestטים שאפשר לעשות אותם יותר פשוטים כ אינפוטים יותר פשוטים זה דבר מאוד חשוב [\[01:43\]](https://www.youtube.com/watch?v=yLBhRenZBeA&t=103s) ופלק ממכם שמו לב שגם אני קצת התפרעתי עליכם מבחינת זה שיש שיש קוד שפשוט לא הייתי מוכן לקבל מבחינת הקריאות שלו וזה חשוב מאוד כי יש איזשהו סוג של מקצוענות שאתם שאתם אומרים על עצמכם אם אתם מתחילים לכתוב בוניטest המקצוע הזאת אומרת לא רק שהקוד שלי עובד אלא אני גם מנסה לעשות אותו קרי ככל האפשר קרי ללא פחות ממה שהטestטים שלי קריאים זה שהטestטים שלי קריאים זה יפה אבל אם הטestטים שלי יש לי 20 טestטים ויש לי פונקציה מפה מהתקרה ועד לרצוה בפונקציה אחת משהו לא בסדר [\[02:17\]](https://www.youtube.com/watch?v=yLBhRenZBeA&t=137s) אוקיי זה מאוד מאוד חשוב כי יש לנו איזשהי איזשהו דגש עלמטיity ככל שהפונקציה יותר ארוכה המטבabity של הסוב וזה משהו משהו שגם לשים דגש אליו בימים הבאים. ביום רביעי אנחנו ניכנס לעולם קצת יותר מורכב שאולי ראיתם אותו קצת בקונסול שניסינו לעשות. מה קורה כשיש לי כשאני אנסה לשלוט בדפטי? פאטי במקרה הזה היה קונסול ואפילו במקרה הזה הקונסול נתן לנו API כדי לשלוט בו. [\[02:47\]](https://www.youtube.com/watch?v=yLBhRenZBeA&t=167s) הוא נתן לנו API כדי להחליף אותו ועדיין זה לא הרגיש ממש נוח. אז אנחנו נדבר על עוד הרבה שיטות איך להחליף דברים כדי שתהיה לנו שיטה עליהם. בעצם כשהחלפנו את הקונסול out עשינו ובדקנו את הסטרינ מה שיצרנו היה סוג של more objects mo objectה שנראה כמו הדבר האמיתי אבל הוא עוזר לנו להחליט אם הטest עבר או לא משהו שהוא [פייק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") אבל אנחנו עושים עליו אסרט ולתצורך העניין יש עוד דבר שהוא פיק שנקרא [stub](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1 "Introducing stubs (The Art of Unit Testing, 2nd ed., ch. 3)") ההבדל בין mor objects לstubs זה שטבס נראים בדיוק כמו מobטקס אבל אנחנו לא עושים עליהם הם מחליפים משהו כדי שנוכל לבדוק משהו אחר אז אז בכל מקרה שיש לכם איזשהו אובייקט שהוא פייק שהוא נראה כמו משהו אחר אז הדרך לדעת אם זה מוקט או סטב זה פשוט להסתכל על הסרטים ולהגיד אם אני עושה עליו אם כן זה מobט אם לא זה [סטאב](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") למה חשוב לנו לדעת את ההבדל ביניהם כי בדרך כלל בטestטים [\[03:44\]](https://www.youtube.com/watch?v=yLBhRenZBeA&t=224s) אנחנו לא רוצים שיהיה לנו יותר [ממוק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4 "Interaction testing using mock objects (The Art of Unit Testing, 2nd ed., ch. 4)") object אחד יכולים להיות לנו הרבה סאבים אבל מ object אחד היותר כי mor object זה בעצם על קריאה לרד פטי זה resultלט ובדרך כלל אנחנו לא רוצים לבדוק יותר מדבר אחד בטestטים. מישהו זוכר למה? למה? >> כן. יכול להיות שאחד נחשב ואחד הצליח ואז אתה לא יודע מהפק. >> בדיוק. אז אם יש לי שני מוק object בטest והאינטראקציה עם הראשון נכשלה, אני אף פעם לא אדע מה קרה עם השני. ולכן מוק objects אני חל מחפש רק אחד הטestטים. [\[04:15\]](https://www.youtube.com/watch?v=yLBhRenZBeA&t=255s) וזה חשוב מאוד לקוד להבין שיש לי הרבה פייקים, אבל רק אחד מהם צריך להיות כמו פרובקט. בכל השאר הם סטבים וזה ה זה הטרמינולוגיה בגדול. יש קונספט כזה ואנחנו נעבור עליו עוד פעם ביום רביעי אל תדאגו אתה בטלוויזיה הזאת אבל תמשיך לקרות פעם אז ביום רביעי תתכוננו ליום טיפ טיפה יותר מסובך מבחינת הפאטרנים היום היה יחסית רגוע הכל ככה הלך בכיף וזה בסדר יום רביעי יהיה קצת דייבים והרבה אנשים אומרים בדרך כלל שביום ביום השני לקורס יש איזשהיא עלייה בדרגה של ה [\[04:49\]](https://www.youtube.com/watch?v=yLBhRenZBeA&t=289s) של המורכבות אבל ביום ביום השלישי של הקורס תבינו שזה לא היה עלייה כזה גדולה ביום השני. אוקיי? כי היום השלישי אנחנו ניכנס ללגסיק. שם באמת המעורבות נהיית מאוד מאוד מסובכת. אבל הטכניקות שאנחנו ביום השני של ריפאקטורים גם בקוד קיים יעזרו לנו מאוד ביום השלישי. אנחנו גם נסתכל על פרימוקים כמוסיקי [\[05:22\]](https://www.youtube.com/watch?v=yLBhRenZBeA&t=322s) די אין סבסיטוט וגם ביום ביום האחרון למישהו אומרים יצא לעבוד עם משהו חוץ מרנו עם מה >> מוק וההפוnet אוקיי בג'אה זה משהו ש קצת ישן והוא ואנחנו לא לא נסתכל עליו היה גם לדוט אבל הוא נפטר מסיירה טובה. אף אחד לא מתפקד עובדית יותר וגם שלו היה די נורא. אה אחד הדברים היפים זה שבדוטנט הרבה מהפרמוקים והרבה מההתקדמות בדוטנט היא הרבה יותר מהירה בג'אבה בעולם היוטיסים היום. [\[05:57\]](https://www.youtube.com/watch?v=yLBhRenZBeA&t=357s) היא יותר מהירה מאשר בג'אבה. פעם ג'אוה היה לה עבר מאוד עשיר של יוניטestינג. זה היה כאן בכל הכלים. היום בטניט הייתה התקדמות ממש ממש מהירה עד כדי מצב שהיום ג'אה והמתכנית ג'אבה לוקחים המון קונספטים שיש ב-NUnit כמו אטריבטס וכולי ושמים אותם ב-JUnit וזה משהו שנורא כיף לחשוב לו כי הרבה פעמים בעולם הדוטנט אנחנו קצת עוקבים אחרי העולם שמסביבנו אז תחשבו על דנט וג'אה אז אז יש גם את עולם הרובי וגם שם הנושא של unit testting הוא מאוד מאוד חזק אבל גם שםש testing בעיקר [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") עדיין לא נכנס כל כך. [\[06:36\]](https://www.youtube.com/watch?v=yLBhRenZBeA&t=396s) Testing הולך חבל על הזמן. אז אנחנו גם נדבר קצת על הפנס of האלה ביום השלישי. אם יש למישהו דברים או שאלות או כל דבר שהוא רוצה לשאול אותי בצורה אסינכרונית אז האימייל שלי כי אנחנו ניפגש רק ביום רביעי. האימייל שזה רואה את אושרדו. אז אתם מוזמנים לשלוח לי אימייל ופשוט לשאול שאלה. להגיד תגידו שאתם קורס כי אני לא אזכור A זה אני סלב ואני אזכור איזה חברהסט [\[07:08\]](https://www.youtube.com/watch?v=yLBhRenZBeA&t=428s) >> מי שלא זוכר את מה שכתוב שם לי יש את האימייל שלו לא זוכר מי זה סלב לא >> כולנו צים להדפיק מי זה סלב >> אבל אבל אני לא יודע איך להגיד לך את זה בכל חברה מצליחה יש איזה סלב אחד שהוא שכותב את כל הקוד הטובת איזה לא זה לאחבר >> רציתי להחמיא לך אבל אתה פשוט זכית אותי >> בסדר זו דחה גם אתה סליחה באתי קודם >> הרחבת אחים טוב בסדר אתה גם אמרת לי קודם שהב שלי באתר לא משהו אז בסדר לא שכוער לא אמרתי שהוא לא משהו [\[07:46\]](https://www.youtube.com/watch?v=yLBhRenZBeA&t=466s) אולי ניפגש ביום רביעי ואולי לא נראה חבר'ה תודה רבה אני מקווה שנהנתם ביום רביעי אנחנו נחזור עלי הדבר הזה אני ממליץ כל בוקר אחר ממחר אתם באים לפה קחו 10 דקות חו רבע שעה תשבו מור למחשב שלכם תלכו על הסטרים קלטור תנסו להתחיל אותו מהתחלה תראו לאן אתם מגיעים ברבע שעה בחצי שעה המטרה היא שתוכלו לסיים את כל התאטה בחצי שעה אבל כולל כל הריפקטורים כולל כל הדברים תראו מה המהירות שלכם בעבודה לבד תנסו וגם זה חשוב מאוד כי זה יזכיר לכם את ה זה מאוד חשוב המסל ממורי בטיפ דין מאוד חשוב אם אתם לא תתרגלו את זה כל בוקר לבחות בשבועיים הקרובים יום אנחנו אתם תשכחו הרבה ממה שלמדתם היום אז קחו 10 דקות כל בוקר תנסו לעשות את הדבר הזה. [\[08:32\]](https://www.youtube.com/watch?v=yLBhRenZBeA&t=512s) בסדר? שאלות טוב לדרו שניה ## Related - [TDD Kata 1 - String Calculator](https://osherove.com/tdd-kata-1) · osherove.com The original String Calculator kata, meant for 15 minutes of daily practice, as Roy asks the group to do each morning. - [Mocks and Stubs - The difference is in the flow of information](https://osherove.com/blog/2007/9/16/mocks-and-stubs-the-difference-is-in-the-flow-of-information.html) · osherove.com Short explanation of the mock versus stub difference that the lesson previews for day two. - [One mock per test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec5) · The Art of Unit Testing, 2nd ed., ch. 4 Book section on one mock per test, the rule the preview states alongside many stubs per test. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 #### The Art of Unit Testing, 2nd ed. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Introducing stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1), ch. 3 - [Interaction testing using mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4), ch. 4 #### osherove.com - [FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition?](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html) [Previous lesson TDD Demo](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/tdd-demo/) [Next lesson TDD Q & A](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/tdd-q-and-a/) --- title: "TDD Q & A" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/tdd-q-and-a.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/tdd-q-and-a/" tags: [] author: "Roy Osherove" description: "Lesson 7 of 22 in TDD in .NET in Hebrew (Day 2 - Mock Objects and TDD), 35:14. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # TDD Q & A 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 2 - Mock Objects and TDD Lesson 7 of 22 Duration: 35:14 [Watch on YouTube](https://www.youtube.com/watch?v=8H69eQeitro) Spoken in Hebrew ## In this lesson The second day opens with participants' questions. Roy Osherove suggests adding a command-line step that [runs the tests in the build](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec1 "Automated builds running automated tests (The Art of Unit Testing, 2nd ed., ch. 7)") and fails it, and on UI testing contrasts recorded WinForms tests with Ruby's Capybara, which can run headless and test JavaScript, while recommending page logic such as validation be extracted into classes that [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") cover. He keeps [DateTime.Now](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec5 "Cross-cutting concerns injection (The Art of Unit Testing, 2nd ed., ch. 7)"), random numbers and threads out of unit tests, gives three ways to test code that ends in storage or a request (abstraction, a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)"), or an [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)")), and advises using [mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") as little as possible. ## Transcript 5,143 words [\[00:04\]](https://www.youtube.com/watch?v=8H69eQeitro&t=4s) זה פשוט או לא פשוט? פשוט יחסית פשוט יחסית >> יחסית יותר קלשר >> אוקיי בסדר אני משום מה היה זכור לי שתמיד צריך לערוך איזשהו כן >> אז זה כבר לא פשוט יחסית זה כבר ממש מסוב אני פשוט לא מצליח לקס זה כמו regular אפר עוד תובנות שאלות סעד מין כלכלה שאלות מהיומיים האחרונים מי ניסה לעשות טסים אוקיי, שאלות שעלו לכם במהלך הכתיבה של הטestטים. [\[00:35\]](https://www.youtube.com/watch?v=8H69eQeitro&t=35s) אם אני אדע את השאלות אז אני אכל לכוון את הקורס קצת יותר טוב לדברים שבאמת נתקעתם. אז באמת התמודדות עם UI בתור חלק מהשלא אם אנחנו אולי זה משהו שנדבר עליו היום. אז אם יש נגיד לוגיקה שבסוף התהליך של אנימציה של UI או איזשהו תהליך כזה שבסופו של דבר אמור להחזיר תשובה שאמור גם להתמודד עם כל מיני סנרז של אינפטים כל כל טריגר כל אלי או משהו כזה >> איזשהו תהליך שזוזר הלוגיקה הפנימית שלו אם אפשר היה לוודא את זה הרי זה טיפה שונה מ אולי האמת אולי זה לא שונה מלכתוב [\[01:12\]](https://www.youtube.com/watch?v=8H69eQeitro&t=72s) כמה סונריוז באותה פונקציה שלא אם בכלל הם בודקים את זה כי אז דיברת על UI שאולי כבר לא עושים לזה מפי סיימות שם פחות עושים לזה מפי סיימות. >> אוקיי, עוד שאלות? >> אה, שאלה שאני הייתי רוצה זה כאילו איפה הגבול שלו ברמה של איזה לוגיקה אסור לנו להכניס אותו? ניתן דוגמה אחד הטestטים היה לנו אוטנ. Now או time spend from second לדוגמה. האם זה דברים שהם כאילו בסדר להכניס אותם מיוני testing [\[01:43\]](https://www.youtube.com/watch?v=8H69eQeitro&t=103s) >> להכניס אותם מיוני טestסים או ב >> להכניס להכניס אותם בטסט >> איפה בעצם הגבול של איזה לוגיקה אסור לי להכניס בטסט >> אנחנו נעבור על זה היום ומחר מצוין שאלה מצוינת כן >> אני עושה פה ציף רגע רגע בוא לפני כן אה נראה מה השם תזכירי ס >> אה יכול להיות שנחסה את זה בכתהליכים שנגועים בסטוריג' מה שהתוצאה של אה כאילו איך איך איך תכתוב למשהו שהתוצאה שלו זהage? אוקיי, בסדר. [\[02:24\]](https://www.youtube.com/watch?v=8H69eQeitro&t=144s) אוקיי, אני רוצה להוסיף סליף לשאלה שלא על day. אם יש לי בקוד שימוש בקבוע, האם בטest אני אשתמש בקבוע או שאני אשתמש במספר? אוקיי כן אנחנו כפים עכשיו כי בתרגול שלנו בעיקר PVD ואבל בפועל אני מניח שנכתוב די הרבה טestסטים לדברים שכבר טובים ואיך איך כדאי [\[02:54\]](https://www.youtube.com/watch?v=8H69eQeitro&t=174s) לעשות את זה איך די סתם >> בסדר רגע לשח זה אותה שאלה זה מה שעשינו >> מה שתעשה ביחד >> כן >> תחיל אני >> אנחנו ניסים לדון זה רק שכולם יודעים אנחנו נסים לעשות משהו ששולח הודעה פשוט רואה ברקוס תרגיל ורצינו לו ידעוד שהוא נשלח אז רצינו לומין כזה אובייקט שעוטף את ההודעה [\[03:25\]](https://www.youtube.com/watch?v=8H69eQeitro&t=205s) אבל היינו צריכים גם לעטוף את ה את הלוגיקה שיוצרת את ההודעה ש למצוא את הקלאס שלנו ולא את הקלאס סודעה אמיתית >> כן >> ואז כל דבר שהיו מבצעים על ההודעה עצמה היינו צריכים להטוף דרך כל מיני דרכים עקומות כדי להעביר פרמטרים לקלאס שוטף את ההודעה כדי שהוא יעביר את זה להודעה כדי שנוכל ממנה לשאול אם היא נשלחה זה התחיל להיות מסובך אחרי שאנחנו רוצים לעשות את זה אז מה השאלה >> השאלה היא מה הדרכים הם יש עכשיו לוגיקה בתוך לוגיקה אנחנו רוצים לבדוק וזה לא כזה מסובך לשלוח עוד יש לך סך הכל קלאס שמשתמש בפ >> כן >> לעשות כאילו [\[04:01\]](https://www.youtube.com/watch?v=8H69eQeitro&t=241s) מה הד הכי מהירה שאפשר לעשות את זה לא ליצור מחדש את כל האובייקטים גם את הקלאס גם את ההודעה גם את התשובה שלה לחשוב מה הקטגוריה של השאלה הזאת אב אני לא יודע and testש לשאלה ההתחלתית אוקיי יתן לנו את ההתחלה של השתשובה כן עוד שאלות אה אני צרה כאילו רק [\[04:32\]](https://www.youtube.com/watch?v=8H69eQeitro&t=272s) לנסח את ספ במינים שלי אני פשוט מרגיש שקראו לנו שם שני דברים אחד בגלל שאנחנו עדיין לא מסודרים עד הסוף עם התשתית מוקינג שלנו שלא רוצה להיות טייפק >> אז נאלצנו לעשות כבר אוכל >> כן אוקיי אז נאלצנו לעשות hand stff וזה היה הסבל שחבינו ביחד שהצורך לעשות כאילו לכתוב את ההנטן ואז כאילו כש כשאתה כותב [מוק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4 "Interaction testing using mock objects (The Art of Unit Testing, 2nd ed., ch. 4)") שהוא אין אז זה פשוט כאילו עבודה יותר קשה לעשות את הסרטים >> אנחנו ניכנס למוקים היום אז אני חושב שלרוב האנשים עדיין יש יחסית מושג חלש יחסית על מושג של מוקינג מול סטאפינג פיגי אז זה היה סבל אחד הנקודה השנייה שזה מה שאתה כתבת וזה מה שאני רציתי לשאול מה פשוט הביס prctices לדוק [\[05:22\]](https://www.youtube.com/watch?v=8H69eQeitro&t=322s) שמש לבדוק תקשורת לבדוק שכש לשלוח משהו איך אתה כאילו בודק שמשהו הגיע לצד השני מה יותר נכון האם אם נכון להשקיע את הזמן שלך בבדיקה שהיא באמת עושה את האינטגרשן או שיותר נכון לעשות את זה isolatד או גם וגם אוקיי מה גרום לך להרגיש רגוע למחד מהסוג הזה בסדר עוד שאלות >> אוקיי אז כן >> דברים הסילכרונים כאילו איך תקן דוגמה למשהו ספציפי שהתר >> לצורך הם בקשה שאני שולח ואני מקבל תשובה מצלת מה התשובה שהייתה לדוגמה >> אוקיי [\[06:09\]](https://www.youtube.com/watch?v=8H69eQeitro&t=369s) >> כן אוקיי >> כן עוד דברים אוקיי מאנשים שניסו לכתוב יוני testingים מי הצליח לכתוב לפחות טestט אחד שהוא הרגיש בסדר איתו אחלה מי מצא באג במשהו מצאת >> מצאתם בגה מצאתם בג צנופ ש מייצרת מ מ מ מ מדייט היא מייצרת כמה זמן עבר איזשהו סטרינטר ו שאנחנו שמשים באיזה כל שיש בדה נקוד סינה אנחנו ישים באיזשהו [\[06:42\]](https://www.youtube.com/watch?v=8H69eQeitro&t=402s) איזשהו קלאס שנקרא טים שנותן לנו סנ פחות איזשהו דלטא מסתבר שהוא לא נותן את הוא לא מתייחס לך השנה השנה של המזק 1 סוג של פעם בחיים לא תקבל זה ניסית למצוא את זה ביחד >> כן >> אחה מה איזה באג אתה מצאת את היד של >> לא לא אני סתם ירוד >> אני >> כן >> אני לא זוכר אבל הבאתי קצת השבוע שבנו טestטים [\[07:12\]](https://www.youtube.com/watch?v=8H69eQeitro&t=432s) בתוך העניין במה מצאת באגים לגמור אני לא זוכר מה עשית צ אוקי מישהו עוד מצב בג שהרוצה ספר עליו אוקיי מי כתב את ולא כאילו שבסדר את זה על מה >> מה שעשינו ביחד על הרqu >> כן אני לא זוכר שזה בקשה נראה לי אומר שכן כן אני לא זוכר >> בסדר מי ניסה לכתוב טסים ולא הצליח כי זה היה מסובך מדי על מה ניסה לכתוב טסטים על הפריורק שאני לכתוב יש לי פריימורק שעשה אוטומציה לוב [\[07:51\]](https://www.youtube.com/watch?v=8H69eQeitro&t=471s) לא היה לי מושג גם איך להתחיל את אז רציתי לכתוב את הספים פשוט מה בסדר שלחתי לליד אימייל שלשון וקיצאתי לו שכל אחד ינסה לכתוב איזה טestט אחד או שניים אבל לבחור משהו פשוט לא משהו שמעבר לרמת הידע שכבר עברנו עליה אלא משהו שהוא איזשהו הלפר מוד משהו עם אינפוטים ואטפוטים הנושא של הזמן יכול להיות דוגמה טובה לזה אמ אני ממליץ לא אוטומטית לקפוץ למשהו שאולי אף פעם לא ניסיתם לעשות אלא ללכת לדברים שבאמת נראים לכם פשוטים ולראות שאתם מצליחים לכתוב לזה test אחד ושני אין שום בעיה שתכתבו את זה בMS test עם הנטוסation שלכם כרגע לא יודע להריץ את זה [\[08:32\]](https://www.youtube.com/watch?v=8H69eQeitro&t=512s) דרך אגב כדי להריץ את הטestים של [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)") בתוך ה אטס ים שטס בטבילד נכון אז אני ממליץ בחום אחרי הקורס הזה זאת אומרת ממש היום להוסיף איזה פקודת אקute קטנה של קומנדל line שמריצה את הITexe וזה מחזיר אפס או מינוס אחד אם זה נכשל ואז זה מכשיר את הבילד הבילד אוטומטית נכשל כשמשהו מחזיר מינוס אחד הקומנדס אז אמור להיות מאוד פשוט תוסיפו את זה כדי שיהיה לכם פידק אבית כדי שתרגישו שהטestטים שהוספתם באמת נכנסים והם לא סתם חיים באיזשהו [\[09:08\]](https://www.youtube.com/watch?v=8H69eQeitro&t=548s) בסדר הפידבק הזה מאוד חשוב בחירה פסיכולוגית אתה רוצה לוודא שמה שעשית באמת משפיע על משהו אחרת אתה סתם מרגיש שאתה עושה משהו זורק את זה לחור שחור וזה נעלם אז הפק הזה מאוד חשוב אמ אם תצטרכו עזר סח ח זה מניין כשרטestטים לקח שהוא בובלפ לקח המון זמן עד ש כל פעם תתקמפל ועד שבתם הטסט רץ כאילו זה מאוד לא היה באמת אה [\[09:39\]](https://www.youtube.com/watch?v=8H69eQeitro&t=579s) טסט כזהטי אם הים כמה אני בטוח שלוקח הרבה יותר זמן אפילו לא היה בוב זה היה גיל כן אבל כן >> בסדר אז זה אולי גם ספציפ גם כילו כאילו האם לעשות proקט כאילו [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1 "Defining unit testing, step by step (The Art of Unit Testing, 2nd ed., ch. 1)") per solution או קמה או תחום לוגי או משהו כזה בסלו של נפתח בשביל >> בזה אני אומר אם נגיד היה אולי להביא זו השאלה בעצם האם נגיד לעשות לכל פרויקט או לכל חלק בעצם ה כי הבעיה היא שהפרויקט של היוטestי הוא כללי לכל לסולושן מאוד גדול >> כן אוקיי אז נדבר על זה צוד [\[10:20\]](https://www.youtube.com/watch?v=8H69eQeitro&t=620s) שאלות זה הזמן זמן אם אם לא תשאלו את זה פה אז רק ביום ראשון אני אחזור צריך לעשות קונסלטינג באמת ונוכל לשבת אחד את אחד אבל אם אתם צריכים לשאול שאלה שאנחנו מים שאחרים גם יהנו מהתשובה אז זה פורם טוב לשאול את זה >> מה המספרים הזוכים בלטו שאלה >> עוד שאלה לגבי כאילו איך עושים UI >> אה יש [\[10:53\]](https://www.youtube.com/watch?v=8H69eQeitro&t=653s) >> בסדר מה טוב אז בואו נתחיל דווקא מui אחד ה ככה כשאני התחלתי את הנושא של UI testing גם פשוט בעולם של winפs עכשיו בונפורס אין אין מה לנסות אפילו זה פשוט עולם שכל הטestטים או שעושים נגיד רקורד ואז מפעילים משהו שלוחץ על כפתורים ומייצר סקריפט אחרי זה זה פשוט מייצר טestטים שהם מבחינתity ממש ממש גרוע אחרי שבוע משהו משתנה ואתה צריך לשנות את כל הטestטים או להקליט מחדש זה מהר מאוד מאבד מהערך שלו. [\[11:26\]](https://www.youtube.com/watch?v=8H69eQeitro&t=686s) מצד שני השנתיים האחרונות בעולם הרובי לימדו אותי כמה דברים לגבי testing שהם מאוד מאוד חזקים אז מה שלמדתי שדוגמה UI Web testing זה משהו שכן אפשרי לעשות והוא יחסית היום ממפנימים כמוסלניום פלוספטום js אוקאי ברה אם אתם עובדים עם רובי ואתם יכולים לעבוד דרך אגב עם רובי על ווינדוס שעדיין בודק את הקוד שלכם אין שום מניעה יהיה לכם כלים הרבה יותר חזקים מאשר סדני היום ברובי יש כלי שנקרא קאפי קפיברה קפיברה [\[11:58\]](https://www.youtube.com/watch?v=8H69eQeitro&t=718s) נכתוב את זה קפיברה זה סוג של חיה קטנה דרך אגב וקפיברה זה פרויקט שהתחיל במקביל סלניום ואז בשלב מסוים סלניום וקפיברה התאחדו לסור סקו אחד הוא משלב את היכולות של סלניום עם עוד כל מיני יכולות מדליקות הAPI שלו ד ממש ממש חזק אבל אחד הדברים הימים שהוא מאפשר זה לא רק לעשות אותו פורמציה של הבראוזר ולבחוק שדברים קורים הוא גם מאפשר לך לבדוק ג'אבסקריפט אבל הוא לא מחייב [\[12:32\]](https://www.youtube.com/watch?v=8H69eQeitro&t=752s) זאת אומרת הוא יכול לרוץ headless בלי בראוזר בכלל בלי UI בקנדלי line על איזשהו סרבר איפשהו ועדיין הוא יודע לדמות ג'אבסקריפט כי הוא משתמש בן השר בספריות של Node.js כדי לדמות את הנושא של הג'אסקריפט אנ ואפשר לעשות טestטים ממש חזקים ויצא לי לעשות כמה טestטים שלוב ממש חזקים עם קפיברה וזה פתרון לא רע בכלל כי מה שקורה שבמקום לחפש דברים בUI אז מחפשים דברים בHTML תחשבו על זה כמו jQuery שמחפש דברים עם ID הIDז בדרך כלל לא משתלים ואז המיקום גם לא משנה דברים שרצים בג'אסקריפט אז נותנים שמות נורמליים לפונקציות והם לא משתנות לפחות הפונקציות שהםפליק [\[13:12\]](https://www.youtube.com/watch?v=8H69eQeitro&t=792s) לקבל requוס ולבדוק שמשהו enable או לא enable אז זה יחסית מאוד פשוט לבדוק את הדברים האלה וטestטים שרסים בג'אבסקריפט פשוט שמים להם כמעט סוג של אטריביוט על השם של הטest ואומרים שהוא aing שלא הסנך שהוא JS enable ואז הטest הזה רץ בלי בראוזר בכלל. הטestטים בעיקרון אפשר הטestטים יכולים לרוץ עם ברזר ואז ממש תראו את הפעולות. אתם יכולים להגיד הטest הזה רץ בלי בראוזר. אז אפשר לעשות את כל הפעולות האלה. בעולם של הרוב אני חושב שגם בעולם של הפייטן למרות ששם יש לי פחות ניסיון. [\[13:44\]](https://www.youtube.com/watch?v=8H69eQeitro&t=824s) הנושא של weוב testing הוא הרבה יותר מתקדם מאשר בעולם של הווינדוס כרגע. אבל מה שחזק מאוד זה שמייקרוסופט לאחרונה התחילה להיכנס נורא חזק לעולם האפen זאת אומרת להתקין Node.js היום על מכונת ווינדוס זה אחד הדברים הכי קלים שיש שזה כבר יותר קל להתקין Node.js מאשר היום על על ווינדוס להתקין רובי זה גם זה פעולה ש פשוט פעולה אחת ואפילו אין אפילו נקסט ללחוץ אז ללמוד את הכלים האלה ללמוד את הסקillילס החדשים האלה יכול לקחת אתכם למקומות חדשים לגב של קונקטיity בטestי אבל זה testing. [\[14:21\]](https://www.youtube.com/watch?v=8H69eQeitro&t=861s) אחד הדברים היפים שגיליתי שכשעושים testing לוב הרבה פעמים בודקים כל כך הרבה דברים דלי שהרבה צורך מוטitט testing יורד. עכשיו זה לא דבר רע שהצורך בניטestינג יורד אבל צריך תמיד איזשהו סוג של שילוב. הוIT testting נותן פידבק מהיר. Testing נותן פידבק מאוד איטי. אינטגרש testing בדרך כלל מריצים בניn buildד ואז הפידבק שאתה מקבל יכול לקחת שעה יכול לקחת גם 24 שעות. ולכן יש מקום חשוב מאוד לunit tests אבל הטגרation testing לפעמים בעיקר הנושא של הג'אבסקריפט בUI מאוד מאוד חשוב [\[14:54\]](https://www.youtube.com/watch?v=8H69eQeitro&t=894s) אבל יש עוד סוג של לוגיקה בUI אם הלוגיקה שלכם היא ברמת הדף לדוגמה validationש שצריך לבדוק 17 סוגים של ולידציה אפשר לבדוק את זה באינטגרש test אבל הרבה יותר פשוט לעשות אקסטרctט ללוגיקה לקס נפרד ממש לקלס לא אתם ישירות לזה ממש לעשות אבסטרקטור לבדוק את השכבה ממש מתח תחת לui וזה גם משהו שגיליתי שמאוד מאוד עוזר זאת אומרת שהUI בסך הכל משתמש בקלאסים שיש להם רק הכי Simple return values ואת הקלאסים האלה אנחנו testing והם תסים הטestטים האלה זה מאוד חשוב כי בעיקר בדברים האלה שיש לך 100 סוגים של בדיקות כדי לעשות לראות שמשהו באמת ולידי אה סם הדברים האלה הם נותנים המון המון ערך לכתוב אינטגרש טest זה עדיין יחסית מסובך זאת אומרת מסובך לדוג שהטest שכתבת הוא נכון ולהריץ אותו לוקח זמן זה עדיין לוקח יותר זמן שלריסט testים [\[15:51\]](https://www.youtube.com/watch?v=8H69eQeitro&t=951s) יש יתרון הפידבק המיידי של יוני testingים אפילו אם הוא לא לטווח ארוך אם הוא קשה לתחזק אותו אז רק בשביל לבדוק סנריוז ו ולעזור לך בכתיבה השוטפת ואחרי זה אפילו אם אם אם הוא לא מתקמפל אם יש לי תו איזה בעיה לזרוק אותו אחרי זה >> אפשר אפשר לזרוק את אחרי זה אני אני חושב ש >> זה ממש ממש חבל לזרוק לא ברור ולכן לא הייתי עושה משהו שהייתי יודע שאני עומד לזרוק אותו אלא אלא אם כן הייתי יודע שמה שאני עובד עליו זה זה משהו שזה בסדר אחרי זה לזרוק את הפודקש עוד כי מה הבעיה עם זה שאתם זורקים טestטים זה שאתם לא יודעים אחרי זה אם תשברו את זה עוד חצי שנה איך תדע ששברת את הלוגיקה הזאת אז זה כמו הקבות בחול ים אתם צריכים לדעת מאיפה באתם כדי לוודא שכל הדברים בדרך עוברים אז אם אתם מוחקים את העקבות האלה אתם לעולם לא תגידו אם בדעתם את זה וטחו לכתוב את זה עוד פעם או ש פשוט לא תפת תגחו בטסטים שלכם אז בדרך כלל אני אנסה לא למחוק שום טסט אחרי שהוא כבר עובר בסדר ואז ואז מה שאני [\[16:51\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1011s) חושב מה שאני עושה לעשות זה לבד שהוא מי טנבל בדרך כלל אם עושים אבסטרקציה מהui ולא בודקים את הui בכלל כיוט אז הטסטים די מט אבל זה לא כזה בגדי בסדר דברים שלא כדאי לכתוב בטסטים זה אנחנו נדבר יהיה לנו סשן שלם על best prtic אבל דוגמה dayט time now אני בדרך כלל זה סוג הדברים שאני לא כותב בesting כי מה שאני עושה זה שטestים שטestים יהיו consistent שטtest כשהוא רץ ועובר הוא תמיד יהיה אותו test אם אני משמש בדdיים now בטest שלי אז כל פעם שאני מריץ אותו זה טסט אחר שט שאלה עוד פעם לגבי הUS שאני מחזיר אותך אחורה >> [\[17:33\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1053s) השאלה הייתה כאילו האם נכון הולך לעשות בדיקות לui אבל אולי צריך לשאל את זה אחרת כאילו לא מעניין אותי לעשות אוטומציה לאui אני רוצה לפנות את הפונקציות בקוד ב נקרא לזה או בג'אבסקריפט >> כן >> ואני מצפה שיש >> יש יש קוד ויש ג'אבסקריפט חשוב מאוד להפריד ביניהם >> אוקיי סבבה תייחס כרגע לקוד בינדס כאילו אבל >> סבבה אז אני יכול לעשות טestטים שפשוט מפעילים את הפונקציה של הבטנו קליק אובר ואני מצפה לראות האם מפעילים את הבטון נקודה enableד [\[18:04\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1084s) כאילו זה לא בדיקת UI זה בדיקה של הקוד שלי של הלוגיקה של הקוד >> נכון >> לא לא טוב כאילו לא כדאי לעשות את הטestטים האלה >> אפשר לעשות את הטestטים האלה ואני צריך להבין כן ש יש סוג של overפification מה זה overפication שאתה בודק את הדרך שבה משהו נעשה ולא את התוצאה הסופית אז אני אתן לך דוגמה הפעלת פונקציה בג'אבסקריפט ובדקתי שהיא קוראת לפונקציה אחרת בג'אבסקריפט האם בסופו של דבר זה אומר שהיוזר יראה שיש כפתור לא בהכרח זה שהפונקציה היא נקראה זה לא אומר שהכפתור באמת שם אולי הפונקציה נקראת אבל אולי אבל אולי היא מפעילה את הכפתור הלא נכון [\[18:40\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1120s) מכוון קנה לגבי דברים שהם בקוד בינ אם אני אם בסופו של דבר הפונקציה צריכה להשפיע על הI אין שום תחליף לאנגרation testing למה לא יכול לעשות כאילו כמו סוג של מוק על הבטן נגיד כן אבל אין תחליף לאינטגרש testing ברמה כזאת שאתה יודע שאפשר לעשות פעולה מההתחלה מאיפה שאני משתמש רואה את זה אין שום תחליף לזה כי לפעמים הטestטים יכולים לשקר >> אבל התוצאה יכולה להיות שנגיד אין אקספtion או שיש אקספtion זה גם יכול להיות איזשהו שלב זה לא אומר שאין ערך זה אבל אתה צריך להיזהר ולא אתה לא יכול שיהיו לך רק יופי טס בוא נני כיסית את כל הפרויקט שלך בטסטים כאלה לא הייתי אומר שהייתי סומך על הטestטים האלה שבאמת הדבר הזה עובד הייתי עושה אטגרש testing כדי לדוד [\[19:27\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1167s) מה >> זה נכון לגבי כל unit test >> נכון אבל יש unit testים שהם של framewורקים ואין להם בכלל ui שם אין לך מה לבדוקation testם כן הם שומרים לדatס יכול test שעובד עםס אבל יש ui שבו אתה אומר האם משתמש רגיל יכול להפעיל בכלל את הפונקציונליות ולעשות את הפעולה שהוא היה אמור לעשות אז שניים שלושה אטגרש test על 100 testים זה לא דבר רע עדיין צריך אותם בסדר אז כן יכול להיות שהייתי כותב את הטestטים לכל הלוגה ועושה אבסטרקציה ועושה [פייק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") שבאמת קראו לכפתור ושעשו לו enable אבל בסופו של דבר אין תחליף את הדבר הזה בסדר [\[20:05\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1205s) ולכן אני ולכן הרבה פעמים בפliקש הערך הכי גדול שהסדתי זה שאני יכול לעשות אט TO סנריו להתחיל ממנו והסנריו הבסיסי עובד ואז אני מתחיל למלא עוד פונקציונטות עם הרבה יני testingים אבל בדרך אני מוטא שלא שברתי את הN פונקציונליות של הזר הוא עדיין יכול לעשות לוגין אוקיי עכשיו בזמן שהוא עושה לוגין מה מופיע האם הזה של הטוויטר מופיע האם הזה של הפה מופיע האם הזה enable כשזה לא enable אבל אבל הנסר פתאום הדף לא עולה בגלל שהמפינס [\[20:40\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1240s) של הקונפיגורציה לא אוקיי הכל יכול לקרות אתה לא יודע מישהו בא ועשה קומיט למשהו בקונפיגורציה מלפני חודשיים אז עשה שום יוניטסט לא לא יבדוק את זה בסדר אני רוצה להציע לד עוד משהו כי היה לנו כן באגים ש שיונית היה אמור לעלות עליהם אם אנחנו נפריד את השכבת UI ל למינימום אז כאילו שכבת צריכה להיות מינימלית [\[21:11\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1271s) חשוב מאוד שלא יהיה לוגיקה בUI אם יש לוגיקה בUI ברמה של ג'אבסקריפט עדיין אפשר לזוק את זה בג'אסריפט frameס כמו גזמי אבל אין תחליף לאינטגרש test המלא שהוא אומר שאפשר אני חובר ואני עונה והדף הזה עולה והדף הבא עולה בסדר והנושא של איזה טestטים כן יכולת לדוג וזה דברים אולי שנראה שבוע הבא אני אשמח להסתכל על זה אמ אמ אוקיי אז דברים ש שאני מנסה להימנע מהם בטestטים ואנחנו נעשה הרצאה שלמה על זה אז אני לא אתנס לזה יותר מדי עבור עכשיו אבל בעיקרון אני מנסה שהטestטים יהיו קונסיסטנטים [\[21:51\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1311s) זה אומר שאם הטestט הזה רץ עכשיו עם עם די ט time מסוים אז הוא תמיד ירוצץ עם הדיט time הזה בגלל שאם הוא רס עם time now אז כל פעם שהוא רץ זה בעצם testט אחר והאם יהיה לי באג יהיה לי מאוד קשה לשחזר אותו ואני רוצה שהטest יהיה consיסטנטי זה לאation test ination test אני יכול שיהיה לי ‏numberation test אני רוצה שיהיה לי rדom number אולי אבל בניט test אני לא רוצה rדום number אני רוצה שכל פעם אני אבדוק עם המספר הזה במטרה שלי לא לדוד שהכל עובד אלא להוכיח את הסקיס הבסיסי ביותר הספציפי ביותר שאומר הזקיס הזה מוכח כעובד כי המטרה היא לעשות פונקציונליות שעובדת [\[22:27\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1347s) Testים לא אמורים לכסות את כל הפונקציוני שלא חשבנו עליה הם אמורים לתת לנו איזשהו עמוד שדרה של האפליקציה שאנחנו יודעים שעובד לבנות את העמוד שדרה הזה ואחרי זה למלא את כל הדברים מסביב עם אגרש test ורange וכל הדברים האלה אבל המטרה היא לבנות את העמוד של דר חוליה אחרי חוליה שיהיה לי שלט בסוף שאני יכול להראות למישהו לעשות דמו בסדר עוד דברים באותה מידה גם טרדים ודברים מהסינכרונים אני לא מריץ ביוני testing כי שתהיה לי שליטה על כל הדברים שאני שאני בודק הוIT work שלי צריך להיות infול זאת אומרת להריץ frרדים אין לי שליטה על פרדים אני צריך להרוג אותם אני לא יודע כמה זמן הטסט יקח [\[23:07\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1387s) ולכן כל הוטסים מתבצאים בפרד אחד מבחינתי testing לסטור ending storage זה בעצם אחד מהשלושה end resultלs אתם זוכרים מה מה השלושה end resultלs שיכול להיות work מישהו זוכר exception אבל מה זה exception זה אחד מה עוד יש [state change](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec7 "Testing results that are system state changes instead of return values (The Art of Unit Testing, 2nd ed., ch. 2)") party עכשיו אם אני בודק שמשהו נגמר בסטור אז אני בודק state change כי אני כי זה שזה נגמר בסטורג זה אומר שמשהו משתנה [\[23:44\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1424s) אם זה משנה את הסט של האפליקציה שלי אני יכול לבדוק משהו שנגמר בסטורage זה אמנם יהיה test זה לא unit test כי מבחינתי unit test ששומר דברים לפיילסטם ולדataביס זה כבר לא unit test יקח יותר זמן אוך קונפיגורציה זה לא דבר רע אבל לא הייתי שם אותו בפרויקטים שנקראים unit testס עכשיו הייתי עושה אגרation test ששומרים דברים לסטורage בגלל שבדרך כללסטורג זה סוג של דטבס ואז אני רוצה לוודא שאני יכול לעבוד עם הסטורג שהקונפיגורציות עוזות שהכל עובד גם סטורג לפעמים יכול להיות לוגיקה [\[24:15\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1455s) אבל אני גם יכול אם נורא נורא מסובך לכתוב את סטורג לדוגמה אני כותב משהו שאמור לשלוח מיילים ולקצch serverבר אז להשתמש בסטורage בטestים שלי יכול לקחת המון זמן רק להרים את האchבר בצורה אוטומטית יכול לקחת המון המון זמן לדמות דברים בסטורage יכול לקחת המון זמן איך אני בודק שמשהו מנסה להישמר לסטורג' אבל אין מקום בסטורג' איך מדמה דבר כזה בכלל? כמעט ביטי אפשרי אלא אם כן הטסטים שלכם יקחו שעה וחצי וימלאו את כל הסטורג' במשהו אז יש דברים שאינטגרש test זה בסדר גמור אבל יש דברים שאתה לא יכול להתעמוד בכלל בנגרש test מה קורה אם בסטורage יש כבר את היו value המסוים הזה מה קורה אם כבר אין מקום מה קורה עם out of mורy וכולי וכולי במקרים כאלה אנחנו מתייחסים לסטורage כדd partטy במקרים שבהם אנחנו לא יכולים לשלוט עליו כדי לבדוק [\[25:04\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1504s) אז זה הופך במקום state test לthד party אנחנו בודקים שמישהו הוא קרע לדבר הזה שנראה כמו סטור מי ש את השאלה כן אז אני לא יודע אם זה עונה לך זה לא זה עונה לך על שאלה אה פחות בהתחלה כאילו כי יותר קיבלתי ליוני testing למדוק כאילו כאילו אני יודע אני מבין שאפשר לעשות את זה בנגרש test אבל >> אבל תסביר לי מה אתה אומר כשאתה אומרסטורage אז הוא סטורגד [\[25:36\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1536s) >> אזור סטורג אבל לא מעניין אותי כל כך שזה נכנס לסטוריג' מעניין אותי שזה יצא ומעניין אותי שיצרתי אובייקט נכון שהולך להיכנס לסטוריג' >> לא כל כך מעניין אותי שהוא שהוא באמת בסטורי אז יכול להיות שזה יותר מוק מדברי >> אזו עכשיו ברגע להגיד מוק וכל הדברים האלה how to wr test at end in storage זה אומר איך לבדוק משהו שנגמר בסטורג אז חות שהנה שלי שיש לי אני יש לי לוגיקה גדולה >> יש לי לוגיקה שמייצרת איזשהו אובייקט בסוף כותב סטורג אז האטפוט הוא באמת אני לא מקבל אפוט כשאני קורא לפונקציה הזאת כי כותב הסטורי >> אוקיי >> אבל אני רוצה לבדוק שמה שאני כותב בסטוריג נכון שהיצרתי את האובייקט הנכון >> עכשיו אני אומר בפיזולוגיקה [\[26:16\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1576s) אז זה שוב שכבה של אבסטרקציה >> אפשר לעשות שכבה של אבסטרקציה שאומרת תייצר לי את האובייקט ואז תבדוק את כל הפרטי של האובייקט לפני שאתה שולוגע את כל הסטורג אז אתה גם יכול לעשות פייק לסטורage ואומר אני אני הסטורג שלך תשלח לי את הדבר הזה ואז אבדוק את זה בטestטים זה אחד הדברים שאני עומד לעשות אפשר גם לעשות test שאומר תשמור על סטורג ואז תעשה גט מהסטורג ושיראה שאתה מקבל את הדבר הנכון. כל הדברים האלה הם אפשריים. זאת אומרת או אבסטרקציה והחלפה או אבסטרקציה לגבי זה שבכלל לא צטריך לשלוח לסטורג בטest שלך. [\[26:48\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1608s) אומרת תעשה make לאובייקט שממלא את החוקים האלה כי זה סוג של הלפרד ואז יש לך בעצם אתה בודק return value הפכת את הtest ל return val test שאתה עושה [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") הסטורage ואז הופך לf partטy test וא אומר תשלח את זה לסטורage ותבדוק שהדבר הזה שנראה כמו סטורג' שקיבל את הדבר הנכון או שתעשה אטגרration test וזה בעצם נהיה state תשלח את זה ותבדוק שאתה יכול לעשות גטג זה בעצם הפעולה שאתה אומר וואלה אני יכול לעשות גט אחרי שעשיתי [\[27:19\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1639s) בסדר אז כל אז אז יש שלוש דרכים לעשות את זה ליוטesting בדרך כלל אבסטרקציה זה הדבר הראשון שהייתי מנסה אבל צריך לזכור ופה עוד פעם צריך להיות מאוד מאוד צריך מאוד להיזהר זה שאני מייצר את האובייקט נכון לא אומר שאני באמת שולח אותו לדataביס בצורה נכונה זאת אומרת הייתי בודק את האובייקט הזה שהוא יוצר אבל לא הייתי מוותר על integraation test באיזשהיא צורה אם אתם עובדים עם דברים כמו הזור הזורס סטורג' [\[27:49\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1669s) הPI האלה משתנים כל הזמן מחר מייקרוסופט משנה גרסה ויש איזשהו באג ופתאום אי אפשר לשמור לעזור סטורג אתם רוצים לגלות את זה כמה שיותר מהר חייב להיות לכם אינטגרשט test שרץ ואומר אני יכול לשמור דברים לסטורage בסדר בלי קשר בכלל לכל היוני testingים אני צריך לבדוק שend to end אני יכול לייצר אובייקט ולשמור אותו לעזור סטורג ולקבל אותו חזרה זה סוג של test לוודא שהמערכת בכלל עובדת שאני יכול להריץ דברים בפייפלין בסדר אה דוגמאות את הדברים זה הרבה פעמים שאני יוצר אפליקציות [\[28:19\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1699s) אני כותב טestטים שאני יכול להריץ בקליינסי זאת אומרת אם האפליקציה היאסמרטליין כלשהו אני בודק בסמרטליין שיש לי את הall dirקטורory כל הdependencies ושאני יכול אצלי להעביר להריץ את כל הIT testים וגם אני יכול לשמור דברים לדataביס הלוקלי אם זה esq או דברים כאלה ואם זה [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec3 "Integration tests (The Art of Unit Testing, 2nd ed., ch. 1)") תמיד יש לי איזשהו לא stageing אלא testver שנראה כמו סטיג'ing serverבר ועליו יש לי שניים שלושה משתמשים שאני יכול לדמות עליהם את כל העבודה [\[28:51\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1731s) ואז כל לילה אם לא כל שעה יש לי תמיד איזשהו פרoס מגביל שרץ ואומר כן אתה עדיין יכול לשמור דברים הכל בסדר מין ירוק כזה פשוט ירוק לוודא שהפייפלין שלי נקי והוא לא חסום בשום דבר קונפיגורציות עובדות בסדר אמ לגס קוד אנחנו נדבר בעיקר על הלגסי קוד גם לקראת סוף היום היום וגם הרבה מחר אז [\[29:23\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1763s) אין לי כל כך מה להיכנס לזה בגלל שזה פשוט זה יסבך אותנו עוד יותר עכשיו איך לב לשלוח recquוס ולבדוק שהוא נשלח אז עוד פעם זה אותו דבר כמו סטורג' אני יש לי שלוש דרכים לעשות את זה או לעשות אבסטרקציה לדבר הזה ששולח את הרquוס ולבדוק שהרquס שנוצר הוא נכון כל הפרטיז מה שזה לא יהיה או לשלוח את זה למשהו שנראה כמו המקום שאמור לקבל את הרqu זאת אומרת לדמות את הhtpסבר ברמה מסוימת או לעשות interpration test ולעשות בעצם state change להגיד אני שלחתי את הrequest עכשיו אני יכול לעשות עוד request ולקבל רפונס אחר [\[29:59\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1799s) בסדר אז אין פה הרבה זה תמיד השלוש אפשרויות האלה איזשהו סוג של אבסטרקציה או fake אוטגרש test אז אין לך בעיה יש לך באמת לוגיקה אני שתמד ‏H http server יכול להיות שתשנה משהו בצד של הסרבר והטest יעבור אבל זה לא יור נכון זה אחד הדברים שאנחנו נלמד היום זה שכשאנחנו מדברים על קס ופיקס וכל הדברים האלה אלה הטestטים שהם הכי פחות הכי פחות מטable אני מנסה להשתמש במוק objects כמה שפחות בטestטים שלי זה אלה הטestטים הכי מסוכנים והכי מסובכים [\[30:33\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1833s) והסיבה שהם שהם מסוכנים זה בגלל שהטבילי שלהם מסתמך על איזשהוטל במערכת זאת אומרת אם אני כבר עושה פיק למשהו אני מוודא שהמשהו הזה יש לו API כמה שיותר קטן אם אני עושה פייק למשהו עם API מאוד מאוד גדול אז א' זה נורא מסובך לעשות זה גם נורא קשה לקרוא וגם הסיכוי שזה ישתנה בעתיד הוא הרבה יותר גדול ככל שהpi יותר קטן אז אני עושה אפילו אבסטרקציה לapi לAPI עם פונקציה אחת ואז לזה אני עושה פי כדי שהטסט שלי יהיה יותר קרי ויותר פשוט [\[31:03\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1863s) ואז אני לא מסתמך על זה שמחר הזה ישתנה כי יש לי אבסטרקציה משלי שאני שולט עליה על החלוטין אוקיי אז כל הנושא של מobs וכולי אלה הטestטים שאם יש לכם יותר מ-5% מהטestטים שיש להם obקס אז יכול להיות שאתם אתם עושים לזה בדרך כלל testים אני אוהב שהם או resultל based או state bas זאת אומרת אני מעדיף לבדוק הכל בזיכרון ולבדוק שמשהו עבר גם 17 קלאסים ואני יכול לקבל חזרת הרי resultלט ושהטestטים האלה יחזיקו מעמד הרבה יותר זמן מאשר הטestטים עם obקס [\[31:36\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1896s) עכשיו זה לא הכל כזה זה שחור. הרבה מהפריורקים היום מנסים לחסוך המון מהmaintainability is אבל זה תמיד יהיה יותר מסובך לכתוב testים עם מוק objects מאשר בלי. אז אז אז הגיידליין פה הוא להשתמש בכמה שפחות מוקס, כמה שפחות סטס, אלא אם כן אין ברירה. בסדר? אסינכרוני בדרך כלל תלוי מה אתה מרוצה לבדוק באסינכרוני. מה אתה רוצה לבדוק? [\[32:06\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1926s) יש לך שתי שני סוגים של של בדיקות. אתה יכול לבדוק שהעבודה האסינכרונית נעשת נכון. לדוגמה, יש לי שלושה טרידים ואני רוצה לוודא שאני לא יוצר דדלוק או שאתה רוצה לוודא שהלוגיקה שכלד מרי סינר. זה שני סוגים שונים של בדיקות. אחד מהם זה אינטגרש ואין שום דרך אחרת והשני מהם אתה יכול להפריד כל אחד מהם ללוגיקה שלו. לבדוק אותו בטסט. בלי קשר לשום דבר. אז אני לא יודע לאזמן את המתק. אוקיי האמת דיברתי על השני אבל הבנתי להפריד את זה בעצם כלסרד יש לו לוגיקה משלו ואתה בודק אותה כest work כלד אמור לייצר איזשהי תוצאה אחרת למה אתה מריץ נכון אז כלד שלו בסדר יכול להיות שגם 17 יכול להיות שזה לולה שעושה 17 דברים אבל זה עדיין כל אחד מה אתה יכול לבדוק במפר של הטestטים לא צריך שלושה אחר להריץ אותו ואם אתה צריך אז תעשה אבסטרקציה שתוכל להריץ כל אחד מהם סתם קרה לפונקציה [\[33:02\]](https://www.youtube.com/watch?v=8H69eQeitro&t=1982s) בסדר רגע אבל יש פה בעיה של פאבליק שלפט וכאלה לא תגדיר בעיה הוא יכול להיות שסרד אחד הוא לא קבל חיצוני אז כל המתודות שלו היו פייט אז יהיה לי קשה לבדוק אותו >> לפרד אין מתודות מבחינתנו >> הפונקציות שהוא מפעיל הם קלאס תחשוב שאתה עושה אינקפסולציה של של קלאס שרד מבצע לאיזשהו קלאס אחד והפרד הזה מפעיל את הקלאס איזשהו פונקציה פאבליק הרי בסופו של דבר כל סרט צריך לעשות תמדוק לפונקציה נכון יש לו איזשהי >> פונציה לא לקס >> אבל הפונקציה צריכה להיות על קלאס כלשהו >> נכון >> במקום שזה יהיה סתם על איזה פונקציה שהיא לא מחוברת לשום דבר זה תהיה איזשהו פונקציה על קלאס שעושה את העבודה והוא אחרי רק להפריד מחר תהחלק את הקלאס הראשונים בהחלט משרן לך את הדיזיין כדי שהוא יהיה יותר testable יותר קרי [\[33:48\]](https://www.youtube.com/watch?v=8H69eQeitro&t=2028s) >> אגב זה עוד שאלה שמא לא לא לשאול אבל באמת הנושא של prיבטateפbליק וכאילו בעצם כל מצב שאני רוצה לבדוק חיזת להיות פאבליק נכון בהגדרה ש >> שום דבר לא חייב בוא נגיד ככה לא חייב אבל בהחלט מומלץ אין פה חייב בדבר הזה באנטגרש test אין חייב בכלל וניטest מומלץ מאוד בגלל שככל שאתה בודק יותר דברים שהם prיבט אז הסיכוי שהם השתנו בעתיד הם הרבה תעולות או יותר גבוה והמטנבity יורד אז הייתי אומר ש99% מהזמן פאבליק זה הדרך הטובה ביותר עד שאין לך ברירה אין לך ברירה לדוגמה אם אתה מנסה להחביא קוד בגלל סקיור [\[34:27\]](https://www.youtube.com/watch?v=8H69eQeitro&t=2067s) בדרך כלל יש לך ברירה ברירה היא די פשוטה לדוגמה במיין מטוד עשיתם אותו אתמול פאבליק אף אחד לא מת מזה נכון חושב כולם פה אז אף אחד לא מת בסדר עכשיו יש את הנושא דרך אגב יש ויכוח שלם של אנשים ש ש לא אנשים יש ויכוח שלם של סוג של אמונה כמעט שגטורינטד זה עם קפסולציה והכבעה של פונקציונליות כדי שאף אחד לא שתמש בה. [\[35:01\]](https://www.youtube.com/watch?v=8H69eQeitro&t=2101s) אבל הנושא של object oriented בtesting הוא קצת משנה את התמונה. הרבה פעמים הוא אומר שאם אתה לא מצליח לבדוק משהו אז יכול להיות שהדיזיין שלך הוא לא testable מספיק לעשות ## Related - [Automated builds running automated tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec1) · The Art of Unit Testing, 2nd ed., ch. 7 Automated builds running automated tests, matching the advice to run tests in the build and fail it. - [I changed my mind - Mock objects are wrong for database unit testing](https://osherove.com/blog/2004/12/10/i-changed-my-mind-mock-objects-are-wrong-for-database-unit-t.html) · osherove.com Roy's reasoning on faking versus integration-testing database code, one of the storage options discussed in the lesson. - [You don’t need mock objects most of the time](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5) · The Art of Unit Testing, 3rd ed., ch. 5 Book section arguing you don't need mock objects most of the time, as the lesson advises. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 #### The Art of Unit Testing, 2nd ed. - [Cross-cutting concerns injection](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec5), ch. 7 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Interaction testing using mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4), ch. 4 - [First steps with NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3), ch. 2 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1), ch. 1 - [Testing results that are system state changes instead of return values](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec7), ch. 2 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec3), ch. 1 [Previous lesson Summary Day 1](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/summary-day-1/) [Next lesson Mocks and Stubs](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/mocks-and-stubs/) --- title: "Mocks and Stubs" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/mocks-and-stubs.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/mocks-and-stubs/" tags: [] author: "Roy Osherove" description: "Lesson 8 of 22 in TDD in .NET in Hebrew (Day 2 - Mock Objects and TDD), 24:52. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Mocks and Stubs 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 2 - Mock Objects and TDD Lesson 8 of 22 Duration: 24:52 [Watch on YouTube](https://www.youtube.com/watch?v=mH5XkOTC2co) Spoken in Hebrew ## In this lesson Roy Osherove explains why a test replaces a dependency, using a manager class whose save method calls a logger that may be unfinished, buggy or slow. He adds [a logger interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)") [passed through the constructor](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_72 "Constructor injection (The Art of Unit Testing, 3rd ed., ch. 3)") and a [handwritten fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec3 "A simple handwritten mock example (The Art of Unit Testing, 2nd ed., ch. 4)") logger in the test file; a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") is a [mock](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") when the test asserts on it and a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") otherwise, as in a second test where a stub logger throws and a fake web service is asserted. He advises [one mock per test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec5 "One mock per test (The Art of Unit Testing, 2nd ed., ch. 4)") and [no logic in fakes or tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_141 "Avoiding logic in unit tests (The Art of Unit Testing, 3rd ed., ch. 7)"), and shows NCrunch running tests in the background. ## Transcript 3,530 words [\[00:01\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1s) עשה אותו יותר testable וגם מבחינתך הדיזיין משתנה. זה איזשהו שילוב בין שתי הגישות האלה. לא חייבים להיות דתי לכיוון אחד ולא חייבים להיות דתי לכיוון שני ככטי. זה אומר שאני מעדיף לא להשתמש בדברים כמו טייפנוק כי הוא מאפשר לי לעקוף את כל הדברים אם אני לא חייב. אבל אני מבין שצריך צריכה להיות לי את הבחירה כי לפעמים הדיזיין הנכון הוא כן לעשות משהו סטטי. אוקיי? אנחנו נראה שסטאטי מבחינת הטestטים הבסיסיים מאוד קשה לבדוק אותו. מאוד אי אפשר להחליף אותו לפחות בדיפאולט [\[00:32\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=32s) אבל אבל סטי זה לא תמיד דיזיין גרוע אז לא תמיד זה שהדיזיין הוא לא testable אומר שהדיזיין גרוע אבל הרבה פעמים זה שמשהו לא testable זה לא כזה דבר רע לעשות אותו testable זאת אומרת אין פה איזשהו גיידליין אחד קשוח וסטנדרטי אבל כאיזשהו משהו שתמיד יהיה בראש עדיף לי שהent שלי יהיה פאבלי ואם אני עושה את זה בtd מן הסתם הוא יהיה פבליק אני לא צריך לחשוב על זה יותר מדי. תחשבו שיש לכם פונקציה שהיא publicליק ואז אני עושה ל15 prvטate methods. [\[01:04\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=64s) אז מה אם יש לי 15 prvט meods? אני בודק רק את הפאבליק והוא כבר מכסה את הפרrivateסs נכון? אז זה מבחינת הדבר הזה אני מקווה שאני איתי ואם יש שאלות אז פשוט תשאלו compפי time זה קשור לקונפיגורציה הרבה פעמים או לעשות סלושן יותר קטן או בסution יש לך solution configuration יש לדבגס אפשר לעשות גם test configuration שלא בהכרח מקמפל את כל הפרויקטים רק משאיר את הבינריies האחרונים ואז כל הבילד לוקח הרבה פחות זמן זאת אומרת כל אחד יכול לעשות אצלו קונפיגורציה שמתאימה לסוג העבודה שלו אם אם אני רק עובד על מודול מסוים וכל האחרים לא הולכים להשתנות מבחינתי אז אני יכול לעשות קונפיגורציה בסולושן [\[01:46\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=106s) שלא עושה בילד זה הכל זה הכל אבל בבילד שלי ובconסטגרש אני משתמש בקונפיגורציה שכן עושה ואז אני יכול יש לי כמה דרכים לשחק ע עם הנושא הזה אני אישית יותר אוהב שיש לי solולשן סוג של עבודה אבל גם השתמשתי בנושא של קונפיגורציות תמיד יוצא קצת מוזר אבל אה זה זה לא לא כזה בגלל בסופו של דבר [\[02:18\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=138s) נוצרו עוד שאלות מהתשובות האלה >> טוב יאללה אז בוא נדבר על פסיד את השאלה >> זה מי >> האמת הייתי שם לך לשמוע על עוד המלצות שלך לג'אהריפט אני לא ממוחה בג'אבסקריפט testingנ הרבה חברים שנורא נורא אוהבים את זה אני אני עדיין לא בעולם הזה יותר מדי אבל אני אשמח לחקור את זה איתך בשבוע הבא, אבל אם תצטריך המלצות על משהו, אז בהחלט יש לי את האנשים הנכונים לשאול. אז בוא נגיד ככה. בסדר? עוד שאלות? [\[02:57\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=177s) אז אתמול התחלתם את הקלקulator קט ואז בניתם לו סוג של UI איזה consolול אפליקש ועשינו את הדבר הראשון שמתחיל להתקשר להיום שזה החלפנו את האoutטפוט של הקונסול במשהו ש שבשליטתנו רגע אתם רוצה לעשות חמש דקות הפסקה שפה נראים גוי אוקיי בסדר היום אנחנו נדבר על די הרבה דברים קודם כל נדבר על נושא של מobקס וסטא אחרי זה ניכנס לisolation frameworks ולמה אני לא קורא להם frameworks למרות שכולם קוראים להם framework נסתכל על אלה ועל עוד כמה [\[03:36\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=216s) ונדבר על מה כדאי ולא כדאי לעשות כשיש objects test קודם כל הכי לא כדאי זה שיהיה לכם object בוא נתחיל עם זה אם אתם כבר חייבים object כי הend resultלט היחיד שלכם זה third partט לאיזהגר או לאיזה סטורג או מה שזה לא יהיה ונורא קשה לעשות לזה פיק נורא קשה לעשות לזה אז משתמשים במקס מרגשה לשתות אז בואו ניקח מקרה יחסית סטנדרטי או מקרה פחות סטנדרטי ממה שראינו אתמול יש לי קלאס שנקרא logג maner [\[04:09\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=249s) יש לו איזשהו deפנendency הוא משתמש בלוגoger שהוא מקבל בקונסטרקטור עכשיו הדרישה שלי היא שכשאני קורא לפונקציה save ושולח לאיזשהו אובייקט אם האובייקט מכיר איזשהם propפרerטies מסוימים נגיד שהוא גדול מאיזשהו ביס מסוים אז אני שומר ללוגר את את איזשהו מידע סך הכל אדנ הכי פשוט הפונקציה save לא מחזירה resultלט זאת אומרת זה לא value test אני לא יכול לעשות פה state p test אלא אם כן אני משתמש באיזשהו פייל syסטם זאת אומרת אני יכול לעשות פהסate testing אם אני מייצר לogגן maner שולח את הלוגoger מוודא שהוא מקונפג לשמור לאיזשהו פייל לוקלי [\[04:50\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=290s) קורה לסייב עם האובייקט הנכון ואז אני הולך ובודק שיש לי משהו בפס שיש לו את הטקסט הנכון זה אם הייתי עושה את זה זה גם [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)") אבל גם st testר test שלא מקבל val אלא רק בודק שיש משהו שונה במערכת המערכת נראית קצת אחרת אבל יכולות להיות בעיות עם הלוגר הזה נניח הלוגר הזה כתוב על ידי צוות אחר ועוד לא גמור יכול להיות שללוגר הזה יש באג ואז כל שאני בודק את הסייב הטסט שלי נכשל גם שגם גם למרות למרות שסייב עובד בצורה מושלמת. [\[05:25\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=325s) אז הטestט שלי נכשל בגלל משהו אחר לגמרי. וללוגר יש טestטים משלו בפרויקט נפרד אבל הוא עוד לא גמור. אז הוא עוד לא עובד כמו שחשבתי שהוא יעבוד. יכול להיות שהוא עובד מצוין אבל לוקח לו המון זמן לעשות את העבודה שלו. אולי לוגר לא שומר לפי הסיטם. אולי הוא קורא לאיזה ובסרוביס בדרך. אז לוקח לו שלוש שניות על כל קריאה. אז יכולות להיות לי המון סיבות למה להחליף את הלוגר במשהו שהוא לא נראה. במשהו שנראה כמו הלוגר אבל הוא לא באמת. אבל יש עוד סיבות [\[05:56\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=356s) לדוגמה הייתי רוצה לדמות שהלוגר יש לו התנהגות מסוימת. אני רוצה לדמות מה קורה אם אני לא מצליח לכתוב משהו ללוגפ נכון? תמיד יש לי את ההתנהגות הזאת. מה קורה כשאתה לא יכול לעשות משהו? אבל יכול להיות המון סיבות לעשות משהו כמו שדיברנו על הסטורג out of space out of memory וכולי וכולי. אז כדי להחליף את הלוגר יש כל מיני דרכים שאני יכול לעשות את זה. אני אזכיר לכם הIT of work שלי עכשיו הוא לא רקס אלא הוא save פלוס הקריאה ללוגoger זאת אומרת החץ הזה אבל loogגר הוא לא חלק מהunity of work שלי כי אם הייתי עושה אותו חלק מהunity of work אז הטestטים שלי יהיו יותר מסובכים או לוקחים יותר זמן אני רוצה שזה יהיה [unit test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") הכל צריך להיות בשליטתי [\[06:45\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=405s) אז בישרפ יש כמה דרכים להחליף משהו אני יכול או לרשת ממנו או לממש איזשהו אינטרפייס אז אני יוצר במקרה הזה אינטרפייס חדש למערכת יש הרבה דרכים לעשות את את מה שאני הולך לעשות עכשיו. זאת אחת הדרכים הפשוטות ביותר והבטוחות ביותר. אז אני מוסיף אינטרפי חדש למערכת שלא היה שם קודם. אני בעצם משנה את הדיזיין של המערכת ואומר שבנתן לogגר כלשהו שנראה כמו loger אני שולח אותו לקונסטראקטור ואז לogגן מנג'ר לא יודע מה זה לוגoger יותר. [\[07:16\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=436s) הוא יודע שיש לoger. ואז כשאני קורא לסיב אני רוצה שסייב יקרא לדבר הזה שנקרא. אבל במקום שיקרא לזה בפרודקשן הוא יקרא למשהו מהטestטים שלי. אז בטestטים שלי אני מייצר קלאס חדש. הקלאס הזה הוא לא חלק מהprפודקש, הוא חלק מהtest prוקט. דרך אגב אתם יכולים למלא את הזה פים לראות ש מה זה מקדש? פשוט תעביר את זה אחורה והבן אדם שיצא הכי קרוב שיחק אותם. [\[07:52\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=472s) אז אני עושה את [הפייק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") לוגog הזה אבל מה שנחמד פה זה מכיוון שהדבר הזה נמצא בטקט שלי מממש את האינטרפייס אני יכול לעשות איתו מה שאני רוצה זאת אומרת לא באמת לרשום לפי סיסטם תודה לא באמת לשלוח לאיזשהו acנקובסרביס אני יכול לעשות פה מה שאני רוצה לדוגמה לא לממש שום דבר רק לשים פה איזשהו פג לשים אותו פאבליק אפילו ולהגיד שווה אז עכשיו הטסט שלי יראה אחרת לגמרי אני יכול להגיד [\[08:24\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=504s) תייצר לי פיקר בטest תעתחה לי את logגן מנגר ותשלח את הפייק לוגog פנימה על הקונסטרקטור תקרא לסי עם האובייקט שנראה בצורה מסוימת ואז תעשה אסרט על פייקלגר שיש לו הפילד הזה שאני הוספתי בפל הוא טרו אם הפילד הוא פלסימן שהוא לא נקרא אם הפילד הוא טרו הוא כן נקרא בסדר אז בעצם הדבר הזה זה מה שמאפשר לי לבדוק אם הטest הזה עבר או לא עבר. למה לא קראתי לו מוקog? [\[08:54\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=534s) בגלל שהמילה [מוק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4 "Interaction testing using mock objects (The Art of Unit Testing, 2nd ed., ch. 4)") היא abusוסed. כולם אומרים את המילה מוק אבל הרבה פעמים לא מתכוונים למה שהם חושבים שהם מתכוונים. פה אני מייצר פייקלגר ובאמת הוא משמש כסוג של מוק object. אבל כמו שאנחנו נראה אחר כך אני יכול לקחת את אותו אוייקט שנראה כמו אובייקט אחר ולהשתמש בו כמשהו אחר. לא רק כמו קוצ'ט אלא גם [כסטאב](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)"). תכף נראה מה יותר. ובגלל זה אני לא קורא לו מוק פיק זה בעצם האנטity או סוג של אנטityי אחד מעל פייק זה משהו שנראה כמו משהו אחר [\[09:25\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=565s) בהתאם לאיך שאתה משתמש בו זה או מוק אוסט אדברים שאני התקנתי פה ושאני אשמח שאתם גם תתקנו ותנסו התקנתי את הדבר הזה שנקרא NCrunch [\[09:56\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=596s) NCrunch זה בעצם מה שנותן לי פה את השמאלים הירוקים האלה שאתם רואים זה אומר שלכל שורה בקוד וגם בפרודקש קוד אני רואה אם השורה הזאת עוברת כרגע או לא אז אני אתן לכם דוגמה הקלאס שאני הולך צריך לבדוק עכשיו הוא login manager with אוקיי זה הURL הזה כבר לא נכון אבל אל תנסו אותו אקראנ עצמו אפשר להוריד אותו מ ncrunch.net [\[10:30\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=630s) הוא חינמי וראינו שגם כשאתה משנה קוד אפילו אם אתה לא עושה הוא מריץ הוא כבר עושהסי ומריץ את כל הטestטים ברקע זאת אומרת אם אני עכשיו עושה comand בשורה הזאת לא עשיתי סי ולא כלום אתם רואים שזה מתחיל להיות פה אדום אתם רואים פה את הטestטים שנכשיו בצד ימין זאת אומרת הפידבק הוא מאוד מאוד מהיר זה מריץ את זה בשרד מקביל זאת אומרת זה לא פוגע בויזואל סטודיו ככל שניתן אני יכול לראות פה כמה טestטים נכשלו [\[11:03\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=663s) והפידבק הוא מאוד אומר אז אם אני עכשיו מחזיר את זה אז הוא עכשיו מריץ את הטestטים עוד פעם והופ חזרתי למשהו שעובר בלי בכלל להסתכל על הטestטים בלי שום דבר אני פשוט רואה את ה את הבריאות של הקוד שלי אז זה מצוין כשהטestטים רצים מהר. אם יש לכם test הדבר הזה יתחיל לרוץ מאוד מאוד לאט. יש הרבה אופציות פה לעשות לגנור לחלק מהטסטים ולא להריץ אותם. אז בבחינה הזאת הוא כלי די חזק. הדבר היחיד שאתם תגלו זה שמבחינת קונפיגורציה בהתחלה הוא מאוד לא נוח. הוא קצת מפחיד. ואם תרצו אחרי זה אני אראה לכם את הקונפיגורציה שיש לי. [\[11:36\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=696s) אבל אם כתבתם כמה טסים כבר יחסית זה בסדר. למישהו שאף פעם לא כתב טestטים זה מתחיל זה נראה קצת מוזר חזרה לדמו זוכרים דיברנו על הלogגן מנג'ר את הקוד שלי אני שיניתי ויצרתי והוספתי את האינטרפיס שנקרא אני שומר פה את הלוגoger והמטרה שלי היא לבדוק שהדבר הזה קורה הטestטים שלי יצרתי קלאס חדש שנקרא פייקלגר שימו לב שהקלאס הזה הוא חלק מהטest הוא אפילו לא בקובץ נפרד הוא חלק מהטסטים שלי בקובץ הזה. [\[12:11\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=731s) הסיבה היא שאם אני אם אין לי הרבה טestט קלאס שמשתמשים באותו פייק אין לי שום סיבה להוציא את זה לקובץ נפרד. אני לא רוצה שמישהו שקורא את הטestטים שלי יצטרך להסתכל בכמה קבצים כדי להבין את מה שקורה. עוד פעם בטestי מהנושא של רדility החוקים הם שונים לגמרי עם prodctiontion cod. Productiontion cod בדרך כלל הייתי מפריד אבל בטestטים שלי המטרה היא שזה יקרה כמה שיותר כמו איזשהו סוג של manual שהכל נמצא בפנים. אז יש לי פה את הtest הראשון. ‏is login OK when login okay calls loger עכשיו המילה calls היא חשובה זה לא rights to loger calls loger אומר לי שיש קריאה לאobייקט [\[12:48\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=768s) זה אומר לי שאני יכול לצפות שיהיה לי פה איזשהו מוק object אז קודם כל אני מייצר את הפייקoger אבל אני קורא לו בתור משתנה אני קורא לו קoger עכשיו הסיבה ש הדבר הזה הוא מobקט זה בגלל שהוא באמת משהו שנראה כמו אובייקט אחר אבל אני עושה עליו הסרט בסוף המוקגר עצמו אני לא עושה שום דבר מלבד לקחת את הטקסט שנשלח לפונקציה של right שאני אעשה להר ולשמור אותו באיזשהו פבליק fieldס string [\[13:26\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=806s) אז אתם רואים שפה האסרט שלי הכחול פה משתמש בשדה הזה גם קונטרול שיפט f7 אם רשרת פשוט מסמן את כל הages כאשר אדום זה יצירה וכחול זה שימוש אז בעצם מה שאני עושה זה אני מייצר את הפייק לoger מהתחלת לogin manג ע עם המק logger שלי קורה לad user כדי שי את הuser הזה ועושה add is login ואז בסוף אני עושה string assert content על המקטt [\[13:57\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=837s) אין פה שום דבר מיוחד אני יוצר קלאס משלי אני לא משתמש בו בשום framewורק וחשוב מאוד ללמוד לא להשתמש בפריורקים לפחות בהתחלה ואחרי זה ללמוד להשתמש בהם בגלל שהרבה פעמים אתם תגלו שטestטים בלי פרימוק יכולים להיות הרבה יותר קריאים ויותר פשוטים מאשר להשתמש בפרימוורק מסוים לגבי זה >> כן >> הבעיה היא שעכשיו כל אחד יכתוב פייק לוגו משלו כאילו [\[14:30\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=870s) כל אחד ש אין שום בעיה זהמה ש >> אין לי שום בעיה כל הזמן ש תסתכלו כמה הדבר הזה פשוט בטestים אני מנסה שיהיה לי כמה שפחות אינפסטקצר וקomמון וכל הדברים האלה כי זה מסבך את העניינים >> אני עושה לי איזה one או שלוקח לי חמש שניות לכתוב ואני גומר עניין אבל זה בגלל שהapי פה הוא מאוד פשוט אם היה לי עכשיו 20 פונקציות אולי זה כבר לא רעיון טוב לכתוב פה פייקל ואז זה כבר הזמן להתחיל להשתמש בפריורק עכשיו הכוח של פרwורק נכנס אבל לדברים כאלה אין שום סיבה לא להשתמש בזה במיוחד עם האסרטים יחסית מסובכים [\[15:04\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=904s) אם לא סתם הייתי בודק את הטקסט הייתי בודק שהוא contט וכולי עם פרwורים לבדוק שמשהו contטנס לפעמים זה סתם מעצבן הקוד הקוד מתחיל לראות די מגיל עוד שאלות אוקיי מישהו רוצה שאני אעשה סטפו כדי לדבג את הדבר הזה שתראו את הפלow טוב אז זה המקרה הראשון [\[15:34\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=934s) בואו ניקח מקרה שני עכשיו הדרישה היא אחרת עכשיו הדרישה היא שכשאני קורא לסיב ואני קורא ללוגר והלוגר זורק אפtion כן זה המקרה הבא אני רוצה שאם הלוגר זורק אספ תקרא לוובסרביס מיוחד שעושה ואומר יש לך לוגר שאי אפשר לשלוח אליו יותר טקסט כדי שאיזשהו סיסמין יעשה משהו בנושא הזה אוקיי אז זה אותו לוגר שהיה לגרות קודם אני פשוט מוסיף עכשיו עוד פיצר למערכת אני כבר יודע שהלוגר נקרא אין לי מה לבדוק את אני רוצה לבדוק שכשהוא נקרא וזורק exceptפtion אז אני קורא לו servיס אז האינטראציה היא קצת יותר מסובכת [\[16:09\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=969s) אבל עדיין הIT of work שלי אם אני רוצה באמת לבק את הדבר הזה כunity of work אחד גדול אני צריך שיהיה ליגרש test כי אני צריך שיהיה לי סרביס אמיתי וזה כבר מתחיל להיות מגוחך אז אז עוד פעם זה מגוחך כיס אבל זה לא אומר שאיפה שהוא יהיה לי איזה אחד או שניים אמיתיים שבאמת יש ובסרביס ובודק שזה מצליח לקרוא לזה וזה מצליח לדמות אבל הבעיה לדמות עכשיו שהלוגר זורק אפtion בטגרש test אם אני רוצה שהלוגר יזרוק exceptפtion איזשהו exceptפtion שאני רוצה אני בנטגרש test יכול להיות שזה יהיה נורא נורא מסובך אז במקום זה אני מחליף את שניהם [\[16:47\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1007s) אז אם קודם היה לי dependency אחד עכשיו יש לי שני dependencies אז אני מייצר שני אינטרפייסים במערכת i loger וi webסice ואני מייצר שני [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") objects במערכת fake loger אולי כבר יש לי ממקודם כן ואת הפייק וובסרביס אני מייצר עכשיו עכשיו בייקובסרס אני עוד פעם אני מממש אותו בצורה הכי הכי פשטנית ש יכולה להיות אפילו בלי propפרeries בו סרביס אני עושה over לפונקציה של הובסרביס שאמורה לקבל את המידע [\[17:20\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1040s) פשוט שומר שם עוד פעם איזשהו פלאג אני יכול לשמור את המידע שנשלח אני יכול לשים פגפס שזה בכלל נקרא או לא ואז אני אעשה עושה ארט ש הWובס ניתח אז במקרה הזה איזה מהdeפendes הוא המק object שלנו אז מה הלוגר הלוגר הוא סטב אותו קלאס שהיה קודם מובקט עכשיו בשימוש הזה הוא סטב זה חשוב מאוד להבין אני לא הולך לעשות הסרט על הפייק לוגog שלי אין לי שום צורך כי יש לי טestט אחר שכבר בודק שהפייק לוגog נקרא אוקיי [\[18:00\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1080s) מבחינת זוכרים שאמרנו לשלושה סוגי result שיש לקוד לunit work פה ללגog manager לס יש לו כבר שני results resultלט אח זה קריאה ללגר יש לנו test לזה resultלט שני זה קריאה לו ועכשיו אנחנו חושבים test לזה זה אומר שבאחד מהם הלוגר הוא מוקצ'נט שנייה הובסרסט אין שום סיבה שפה שניהם יהיו מוקצ'נקט שיהיה לי שני הסרטים על אחד על כל אחד מהם א' בגלל שזה אומר שאני בודק פה שני דברים ואם פתאום מקריעה לזה תיקשה של אני לא יודע אם אני קורא לוובסרביס [\[18:31\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1111s) בשביל זה יש לי את זה בטest מפרד ובחנת השם של הטest יהיה לי הרבה יותר קשה לתת שם לט שאני בודק בו כמה דברים ולכן בטestט הזה אני אגיד לפייק לוגoger לזרוק אספtion וזה הולך להיות מאוד קל כי זה קלאס שלי אני פשוט יכול להוסיף לו איזשהו פלק שאומר שאתה נקרא פשוט תזרוק את האקפש שאני אומר לך ואז אני עושה על הפיקובסice אז הנה הדוגמה לך הייתי כותב את הטest הזה פה הייתי יוצר פייקר 2 זה למטרת הדמו בחיים המצוציים [\[19:03\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1143s) הייתי מוסיף את הקוד החדש לפייקלוגר הקיים אבל לצורך השלטנות של הדבר הזה יצרתי את זה פשוט מראש אז קראתי לו פייקור ש אני עדיין שומר את המידע כמו ששמרתי קודם אבל יש לי עכשיו גם איזשהו fieldד מסוג exception שנקרא will throw ה throw זה פשוט כדי שהtest סט שלי כר נחמד וכל הבדיקה שלי זה אם הול שלי הוא לאנט אז תזרוק את מה שיש בו אין פה hardדקד את הסוג של האפtion אין פה hardcודed את המage שום דבר הטest הוא זה שקובע מהזרק [\[19:42\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1182s) זה חשוב מאוד כי אם יש לי פה דברים שהם hardcודד אז אני לא יכול לעשות ריז לפייק הזה בטסטים אחרים אחר כך וגם הטestט שלי יהיה לא קרי אני לא מבין לא אבין למה האקספtion הזה נזרק עם המסג הזה אני צריך להסתכל בשני מקומות אז עכשיו הטסט שלי נראה ככה קריט תיצור את הפיק log אבל אני קורא לו stoger הפעם stablog will throw new logoer exception עם המessage הזה אתם רואים שעכשיו זה נראה קצת כמו סוג של משפט בגלל זה נתתי לזה את השם הזה [\[20:14\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1214s) אני יוצר את הפיק weובסרס ולא אני קורא מוקסice פה אני משנה פה את השמות כי כ מי שקורא את הטestט אני בדרך כלל אחפש טestטים ואני אוודא שיש רק מוק או obקט אחד אני אראה שיש שני מקוםצ'ט זה אומר שאני בודק יותר מדבר אחד בטס ומה הבעיה עם זה שאני בודק יותר מדבר אחד בטח למה הוא נחשב >> מה לא אני יכול לדעת למה הוא נחשב >> מה נחשב >> אני יכול לדעת מה נכשל אני יכול לראות שבש >> מה קרה עם השני >> אני לא ידע מה קרה עם מה שקרה אחרי זאת הבעיה שלי אז יהיה לי פחות מידע בסוף אני קורא לזגן אוקי אבל אני פה אני מתחיל את הlogin manager with and st בעצם זאת הגרסה של הלogin maner אחרי שהייתי משנה את הדיזיין, עכשיו הוא מקבל שני אינטרפייסים בקונסטרקטור [\[21:01\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1261s) ואולי אתם מתחילים לשאול את עצמכם אוקיי הקונסטור הזה מתחיל להראות קצת מעצבן עכשיו ובאמת בהרבה מערכות כאלה הרבה פעמים יש המון dependencies conסטרctטורים חמישה depפencies ואז יש המון סוגים של רפקטורים שאפשר לעשות ויש גם כל מיני כלים שעוזרים להקל על העבודה במקרה כזה אמ אבל תכף ניכנס לזה אני רק רוצה לראות את הדמו עד הסוף. אז עכשיו הקוד שהייתי אמור לכתוב הוא לא אבל עם try וcch ואז קרא לובסרס [\[21:36\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1296s) לתוך הקטch. בעצם זה המטרה שלי עדה עם הלoger exception תקרא לובסice בסדר והקוד שלי עוד פעם אני מאתחל את ה login manager with m and [stub](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1 "Introducing stubs (The Art of Unit Testing, 2nd ed., ch. 3)") כמובן בפucion קוד אני המילים st לא יופיעו זה רק לצורי דמו אני שולח לו את הסבog ואת המקובסice קורא login אוקי אבל הארט שלי הוא על המקסage [\[22:06\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1326s) המage הזה נמצא פה ‏Fובice אתם רואים שהפייקוב סרביס עוד פעם הוא פשוט עד כדי איכוך ככל שהדבר הזה יותר פשוט יותר טוב לי כי הדברים האלה הולכים לחיות עכשיו 15 10 שנים אם יש לי פה לוגיקה הסיכוי שיהיה פה באג שואף לאחד לאורך זמן בסדר אז אני רוצה שתהיה לי פה כמה שפחות לאר זה הלוגיקה הכי מסובכת שאני מוכן שתהיה לי אי פעם בקלאסים שהם פייק שהם handרי ככל שיש לי יותר לוגי הסיכוי שיש בה ב באג יותר גבוה ואתם יודעים הטest שאתם חושבים שהוא עובר אבל זה בגלל באג בפייקים שלכם זה דברים שלוקח הרבה זמן למצוא אף אחד לא מחפש את הבאגים של [\[22:46\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1366s) ושם דרך אגב [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") בורד עוזר לוודא שהטest שלך נכון אבל הבעיה האמיתית היא שגיל שאתה הטestטים נכשלים ואז עוברים אבל אז 100 טestטים אחרי זה אתה מגלה שיש לך בעפייק שעוד 50 טestטים משתמשים בו עכשיו אתה משנה את זה ו-50 טestטים נכשלים לך בגיל ת שבעצם כל הזמן היה לך בד קטן אז אז כמה שיותר למזר את ה את הבעיה הזאת של לוגיקה בטestטים שימו לב שבטestטים שלי אין שום לוגיקה גם דיברנו על דברים שלא טוב לעשות בטestטים לא טוב לעשות לוגיקה בטestטים יש לכם לולאות בטestטים ביוני testingים אינטגרש testים אין חוקים גרש test תעשו מה שאתם רוצים [\[23:27\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1407s) תעשו פרדים תעשו לולאות תעשו רנדום אבל ביוני testingים אין שום סיבה להשתמש בדברים האלה אז אם יש לכם אי בטestטים כלתם אתם בודקים יותר מדבר אחד. אם יש לכם לולאה אתם בודקים יותר מדבר אחד או שיש דרך יותר פשוטה. אתם צריכים אולי פחות אינפוטים כדי שלא סקו לעשות אוה. זה הסיבה עוד פעם. ככל שיש לו יותר לוגיקה גם יותר קשה לקרוא את הטestט וגם הסיכוי שיש בג בטest הוא יותר גבוה. שאלות לגבי מוקים, סאבים ופייקים? [\[24:00\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1440s) כלום. אמ בסדר. אז מה שאנחנו הולכים לעשות עכשיו זה לקחת חמש דקות הפסקה ואז כל אחד אנחנו מחכים לזוגות ובשעה הקרובה לעשות את ה את הדוקומנט שאתם רואים פה אני אסתובב ביניכם יהיה לכם דוקcumומנט שמבקש ממכם לכתוב מוק objects לכמה דברים כשאתם מגיעים לתרגיל שמבקש ממכם לעבוד עם מ mo mq אז אתם עוצרים ואם ואתם קוראים לי כדי שאני אבוא להסתכל על הקוד שלכם בעיקרון אנחנו הולכים לעשות את זה עד שנגיע [\[24:32\]](https://www.youtube.com/watch?v=mH5XkOTC2co&t=1472s) למוק ואז אני אסביר על [isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99 "Defining isolation frameworks (The Art of Unit Testing, 3rd ed., ch. 5)") ואז אנחנו נמשיך ואז אנחנו ככה בעצם היום הזה ימשיך ככה דוגמאות ואז המשך עבודה ואז דוגמאות ואז המשך עבודה שאלות לפני שאנחנו מפרדים לחמש דקות זמן טוב זה הפסקה ‏Ja. ## Related - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2) · The Art of Unit Testing, 2nd ed., ch. 4 Explains the difference between mocks and stubs: asserted against or not, the definition used in the lesson. - [A simple handwritten mock example](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 4 A simple handwritten mock example in C#, like the fake logger the lesson writes in the test file. - [Using a mock and a stub together](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec4) · The Art of Unit Testing, 2nd ed., ch. 4 Using a mock and a stub together, as in the test with a throwing stub logger and an asserted fake web service. - [Depending on a logger](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_77) · The Art of Unit Testing, 3rd ed., ch. 4 Book section on depending on a logger, the same dependency the lesson's manager class needs replaced. - [Constructor injection](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_72) · The Art of Unit Testing, 3rd ed., ch. 3 Covers constructor injection, the way the lesson passes the logger interface into the manager. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Extracting a common interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74), ch. 3 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Avoiding logic in unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_141), ch. 7 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [Defining isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99), ch. 5 #### The Art of Unit Testing, 2nd ed. - [One mock per test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec5), ch. 4 - [Interaction testing using mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4), ch. 4 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 - [Introducing stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1), ch. 3 [Previous lesson TDD Q & A](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/tdd-q-and-a/) [Next lesson Isolation Frameworks](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/isolation-frameworks/) --- title: "Isolation Frameworks" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/isolation-frameworks.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/isolation-frameworks/" tags: [] author: "Roy Osherove" description: "Lesson 9 of 22 in TDD in .NET in Hebrew (Day 2 - Mock Objects and TDD), 34:31. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Isolation Frameworks 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 2 - Mock Objects and TDD Lesson 9 of 22 Duration: 34:31 [Watch on YouTube](https://www.youtube.com/watch?v=bguE7d1AL7A) Spoken in Hebrew ## In this lesson Roy Osherove explains that [isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99 "Defining isolation frameworks (The Art of Unit Testing, 3rd ed., ch. 5)") generate [fakes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") in memory that return values, throw exceptions and verify calls, and that any fake is a [mock](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") if the test verifies against it and a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") otherwise. He splits .NET frameworks into [constrained ones](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev2sec1 "Constrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") such as [Rhino Mocks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5 "Current isolation frameworks for .NET (The Art of Unit Testing, 2nd ed., ch. 5)"), [Moq](https://osherove.com/blog/2012/6/27/the-future-of-isolation-frameworks-and-how-moq-isnt-it-for-n.html "The future of Isolation frameworks, and how Moq isn't it (for now) (osherove.com)"), [FakeItEasy](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html "FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition? (osherove.com)") and NSubstitute, which can only fake virtual or interface methods, and [profiler-based ones](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") such as [Typemock Isolator](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html "Minimizing unit Test Fragility – 8 features in Typemock Isolator to help (osherove.com)"), [JustMock](https://osherove.com/blog/2010/5/25/justmock-and-moles-a-short-overview-for-tdd-alpha-geeks.html "JustMock and Moles – A short overview for TDD alpha geeks (osherove.com)") and Moles, which can also fake static methods. He then rewrites the logger tests with [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)")'s basic dynamic mocks, Rhino Mocks and Moq, comparing string method names with lambda expressions, strict and non-strict mocks. ## Transcript 4,867 words [\[00:07\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=7s) צריך להגיד פעמים יש ספר שנקרא XIT test מישהו קרא אותו מסתכל עליו ראה את השם כבר XIT test בספר הזה כשמתארים סוגים של [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") objects יש את כל הסוגים האלה לכל אחד מהם יש בעצם זה צורת מימוש אחרת יכול להיות אצל לכם סוגים של סטיק אופט שיש להם כבר מימוש מלא אבל מאוד פשוט יחסית למערכה האמיתית אה מבחינתנו מבחינת הצורה שבה אני חושב על זה יש אך ורק שלושה סוגים של פיקט יש כל דבר שהוא [פייק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") זה בעצם משהו שנראה כמו משהו אחר ובהתאם לשימוש פה שזה או [מוק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4 "Interaction testing using mock objects (The Art of Unit Testing, 2nd ed., ch. 4)") אוסב [\[00:41\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=41s) אז אם אתה עושה או verifיפי אז זה מוק object אחרת זהסט זאת הדרך הכי פשוטה לחשוב על זה אחרי זה כשכבר יהיה לכם יותר נוח עם כל הטרמינולוגיה אז תוכלו כבר להיפטר עם זה יש לי פה איזה סקייפ שרץ אוקיי [\[01:14\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=74s) אוקיי אבל יש גם הנושא של מה שעשינו עד עכשיו יש איתו הרבה בעיות >> יש איתו הרבה בעיות עם הדבר הזה. זאת אומרת, ברגע שיש לנו API שיותר משתיים שלוש פונקציות, זה כבר נהיה קצת מבאס לממש את הדבר הזה. למרות שאני מניח שחובכם כבר שמתי להם שזה די פשוט מה שעשינו עכשיו. ו גם כמות הפרמטרים, אם יש לנו פרמטר אחד מאלה אפשר לשמור. [\[01:46\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=106s) אבל מה קורה כשאני רוצה להתחיל לבדוק דברים כמו מה קרה בקריאה השנייה או האם מתוך 100 קריאות אחת מהם הכילה את הפרמטר המסוים הזה? אז אם הייתם ממשיכים עם הגישה הזאת שנתיים שלוש הייתם מגיעים הייתם מייצרים בעצם אינפסטקצר משלכם שמאפשר לבדוק את כל הדברים האלה בעצמכם וזה בדיוק מה שהisolation frameworks עושים היום זה infrastructure או moring frameworks זה אינפסר שבעצם כבר לקח את כל הדבר הזה צעד אחד קדימה ואמר אני אתן לך משהו שמאפשר לך ליצור קלאס אבל בזיכרון זאת אומרת אני אגנרate אייצר קוד בזיכרון [\[02:21\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=141s) והקוד הזה כבר יעשה אוברייד לכל הפונקציות וכבר ישמור את כל המידע מידה ואז תוכל לעשות verifיפי אוט שמשהו יתקבר או תוכל להגיד לי לזרוק אספtion זה בסך הכל קוד שהוא לא מסובך לכתיבה הבעיה האמיתית היא ליצור את זה בזיכרון ופה באמת הנושא של פריימורקינג נכנס בצורה מאוד חזקה ברגע שיש לנו API שקצת קשה לעשות פייק בצורה ידנית אז פריורקים כמורינוקס מוק ועוד כמה שאנחנו נראה פותרים את הבעיה בצורה מאוד יפה בעצם בשורה אחת של קוד הם מאפשרים לנו [\[02:57\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=177s) ליצור קלאס בזיכרון, ליצור את הקוד שיוצ שיברש מאינטרפייס בזיכרון או מקס אמיתי לממש את כל הפונקציות הוירטואליות או הפאבליק ואינטרפי ווגם לתת את כל הפונקציונליות הזאת של תבדוק שמשהו נקרא או תגרום למשהו להתנהג בצורה אחרת כמו לזרוק אפtion או להחזיר איזשהו value אז גם סימולציה של return values והתנהגות וגם וידוי שמה שהוא נקרא עכשיו הסיבה שאני קורא להם framewor זה בגלל שלמילה מ כמו שהבנתם יש חשיבות מוק זה משהו שעוזר לי לוודא שהטest עבר או לא ברוב הזמן בטestטים שלי אין לי כמעט מוצק ברוב הזמן יש לי stubים שאנשים אומרים I want to mo this out הם בעצם בדרך כלל מתכוונים לזה שהם רוצים לעשות stubb למשהו לכן אני פשוט משתמש במילה פיק ואני גומר עניין תעשה פייק לזה תעשה פייק לזה אחרי זה תעשה וריפי שזה נקרא [\[03:51\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=231s) אבל כשאנשים אומרים obקט בדרך כלל מה שהם מתכוונים סטב עכשיו עוד פעם הסיבה שזה חשוב למה הטרמינולוגיה הזאת חשובה זה בגלל שאתם מסתכלים על טestטים של מישהו אחר חייבים להבין שיש מobק ויש stבס ומק object לא צריך להיות יותר מאחד מהם stבס שיהיו לכם גם 50 בטest זה קצת זה אומר על איזשהו דיזיין זאת אומרת שיש לכם 50 [סטאבים](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") אבל אתם יכולים בגלל הנושא של הוריפיקציה עכשיו כשמד מדברים על [isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec1 "Why use isolation frameworks? (The Art of Unit Testing, 2nd ed., ch. 5)") isolation בעצם אומר שאתה לוקח משהו ואתה אתה עושה לו isolate מהסביבה [\[04:25\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=265s) שמסביב לו, כל הדdeפendנenes שלו, כל הדברים שאין לך שליטה עליהם בדוnet ובכלל יש שני סוגים של וואו isolation framework יש isolation frameworks שמה שנקרא אני קורא להם constraint וuncrain constrain זה בעצם frameworים שמייצרים קוד בזיכרון כמו שאתם יצרתם עכשיו קוד בקפיילר יוצרים ממש מייצרים קוד בil במקרה הזה אבל זה עדיין קוד שיורש מקלס מסוים, מממש את הפונקציות שלו ואת כל המידע ועושה קבקים על כל פעם שמשהו נקרא. [\[05:02\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=302s) והפרamרוקים האלה זה בדרך כלל הפרוקים שהם קונסטר בד.net אני קורא להם prוקoxy בגלל שהפריורקים האלה שאתם רואים מצד ימין הם כולם משתמשים באותו אינפסרקר כדי לעשות את העבודה שלהם. יש DL שנקרא. אטפ C2 למי שמכיר ומה שהוא מייצר בעצם זה מאפשר לך בזיכרון ליצור פרוקסי של כל אובייקט אבל מה זה כל אובייקט רק אובייקטים שאפשר לרשת מהם אם יש לך קלאס שהואסילד אתה לא יכול לייצר קוד שיורש ממנו זה לא יתקמפה לך אז גם מפרים אוקים האלה לא יכולים לרשת מקס שהוא סיל אתה רוצה להחליף פונקציה שהיא לא וירטואלית והיא לא מאינטרפייס אתה לא תוכל לעשות את זה כמו שאתם לא תוכלו לעשות את זה כשכתבתם עכשיו את הקלאס שלכם של פייק לogגר אז אם לפי אם ללוגר יש פונקציה סטטית אי אפשר לעשות לה [\[05:49\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=349s) וגם מוקים האלה לא יודעות לעשות להם או כי כל הפרוקסי כל הקסל אקטיב prוקסי על הדרך שבה עובד זה הוא מייצר קוד כמו שאתם מייצרים אותו רק בזיכרון מקמפל אותו בזיכרון ונותן לכם את הקולב בקן את היכולת לבדוק שמשהו נשמר עכשיו כל הפרים אלי הם גם open source והם חינמים אמ אני כבר לא מאמין להשתמש ברינו אוקס למרות שפעם המלצתי אפילו כאילו כתבתי את הספר שלי עם דוגמאות מרנוקס אבל בגרסה הבאה של הספר אני כבר לא משתמש בו [\[06:22\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=382s) אני תכף אסביר nunitס זה framewורק שמגיע יחד עם [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6 "More NUnit attributes (The Art of Unit Testing, 2nd ed., ch. 2)") והוא פרwורק מאוד מאוד בסיסי שמאפשר לנו שבעצם באמצעותו באמצעותו יונית בודק את עצמו בהתחלה כשיוט נבדק אז הוא כתב לעצמו isolation framework משלו אבל הוא מאוד מאוד בסיסי ואין לו המון המון מהפיצ'רים שאנחנו שיש להם בפרימוקים החדשים יותר מוקספ מוק שתכף אנחנו נסתכל עליו חייבים ללמוד אותו בגלל שהוא מרבית את האוכלוסיה שלדות נט משתמשת במוק [\[06:53\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=413s) החצי השני של האוכלוסייה משתמש ברינוקס אנחנו גם נראה דוגמה של רובקס אבל אני לא מועס להשתמש בו הסיבה שהוא כבר פרימוק שהוא ישן מאוד הוא כמעט ולא מתוחזק על ידי היוצר שלו ויש לו שלושה סוגי API והי שלו גם החדש ביותר הוא פחות נוח מאשר הפרימוקים האחרים שני פרוקים חדשים שאני מסתכל עלים זה [FakeItEasy](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html "FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition? (osherove.com)") ו-NSubstitute שזה שני פרורקים שאני ממליץ להשתמש בהם היום כשמדברים על פרמורקים שהם קסטרrain והם חינמים [\[07:24\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=444s) לשניהם יש API מאוד שונים אבל עוד פעם יש להם את אותם יכולות בסיסיות שיש לכל האחרים אז ההבדל היחיד הדבר היחיד שמאחד ביניהם זה הAPI יש להם אותו סט של קונסטרנטים או אותו סט של יכולות בעצם מצד שני יש את הCSTR frameworks בג'אבה יש frameworים שיכולים לעשות fake לstatic methods וגם בד יש כאן ‏frameworים ב.net נותנה את הCor זה בגלל שהם משתמשים בדבר שנקרא פרופיל API וגה זה כי הם משנים את הביטקד של הג'אבה בזמן גם בזמן קומפילציה או גם ברun [\[08:00\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=480s) אז הCstra frameworks בוnet אני קורא להם based כל הפרקים שאתם רואים פה הם profי base הם לא open source המס הוא חינם אבל הוא עולה הרבה מאוד כסף מבחינת תחזוקה אז אני לא ממליץ להשתמש בו אגנו nock ונוק שניהם עולים עם הרבה כסף ג'סמו עולה בערך חצי מה שטימו עולה אבל גם מבחינת הפיצ'רים שהוא חוסף זה בערך חצי מהפיצ'רים למרות שכל יום הוא משתפר אז יגיע היום ויהיה הרבה יותר שווה להשתמש בטסמו מאשר בטייטמו עכשיו אני עבדתי שלוש שנים בחברת טיפורק עד לפני שנתיים עבדתי שם הייתי שם CTO ועזרתי לתכנן חלק מהipi אז כשאנחנו ניכנס ללגס קוד וגם היום אני אראה לכם חלק מהipיים שלנו קסator [\[08:43\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=523s) אבל מה שחשוב להבין זה שזה בסך הכל עוד פרופילר בספר frameworks היכולות שלו הם אחרות לגמרי מהיכולות שיש בפוקסי אבל היכולות של כל אלה הם בעצם אותו סט של יכולות שיש בפרופיילר אז כדי להבין איזה יכולות יש צריך להבין את הפרופי API מי למי יצא לעבוד עם פרופיילר API אוקיי רוב האנשים בדרך כלל לא מכירים את הפרופיילר API בגלל שרוב אנשים לא צריכים להיר אני אסביר קצת על הדבר הזה אה כשאנחנו מריציםקוד של אז בגדול הקוד של net הוא hosted [\[09:19\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=559s) בoccess והוא hosted כסוג של com object אחד גדול והcobect הזה ההost שלו הוא כתוב ב+ בmanage c++ וההוסט שלו נותן סדרה שלטים על כל דבר שקורה במהלך ההוסטינג סוג סוג הדברים שקורים זה הרצה של פונקציה דוגמה בהתחלה של פונקציה בסוף פונקציה עוד דברים שקורים לדוגמה זה שכשאנחנו קוזים קוד אנחנו לא באמת מקמפלים הרי לבנר אנחנו מקמפלים ‏IL ברוב המקרה הCLR הקon language run time כשהוא מעלה את הקוד שלנו הוא מקמפל את ה שלנו לbינaryקוד בזיכרון [\[09:56\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=596s) זאת אומרת יש טרנספורמציה שקוראת מil לbיaryקוד בתוך ההוסטנ וגם לזה יש לנו event זאת אומרת יש לנו את היכולת להתחבר להוקים האלה אך ורק בmaned cod c++ לדוגמהent כמו before module load ובאent הזה אני יכול לקבל את ‏IL של אסמלי כל אסמלי לא רק בכך שלי לפני שהוא מקומפל ל לב לנy cod ויש לי גם את היכולת לשנות את ה בסיכרון [\[10:28\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=628s) אוקיי עכשיו בil אין את אותם קונסטרנטים שיש בשפה כמו C# יש הרבה פחות קונסטרנטים ואני יכול לשנות מה שאני רוצה כל זמן שזה חוקי זאת אומרת אני יכול לשנות את הב את ה של כל פונקציה גם אם פונקציה סטטית אז בגדול מה שרוב הפרימוקים שהם פרופיילר ביסט עושים הם כותבים גוקים לunmanage profיילר api עוברים על i של כל הדברים שנס שמועלים בזיכרון דרך אגב זה עובר על הכל SharePoint גם עובר את התהליך הזה זאת אומרת גם קוד שלא אתם כתבתם עובר את התהליך הזה ויש לכם טבוקים ואתם יכולים לשנות קוד שאתם לא כתבתם בעצמכם והוא לא נמצא בחברה שלכם בכלל [\[11:13\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=673s) ומה שהם עושים בגדול הם מוסיפים לתחיל מילה וסוף של כל פונקציה כל פונקציה בחבי כל הCLR את היכולת לבדוק אם אם כדאי לשנות את את הurn value או את הבי של הפונקציה תחשבו על זה שזה סוג של aspect oriented prraming ברמת כל הפונקציות בCLR אז אני יכול עכשיו לקחת איזשהו פונקציה שהיא private או statטיקrור איפהשהו ואני יכול להגיד שהסatטy conונסטרקטור של הקס של הביס הזה בלגסוד נקרא אז אני רוצה שתזרוק את האקס המסוים הזה out of memory [\[11:46\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=706s) הסatic conסctטור הוא ilגם עובר קומפילציה בCLR ונוסף לו הזה בהתחלה ובסוף ואז ברט time יש את הבדיקה הזאת בהתחלה האם כדאי לי להחזיר fake value או להחזיר exception ובאפtion האלה אנחנו שולטים נשקות שכתבנו בשר מה שמאפשר לי בעצם לשנות את ההתנהגות של כל פונקציה במערכת כולל בין השער פונקציות של של הדסר בעצמו של הדפר אני יכול לשנות את ההתנהגות של day now שתמיד יחזיר את אותו זמן לדוגמה בלי לעשות שום דבר אחר וזה סוג הכוח שיש לנו בדברים האלה אז בפרופיילר ביס פרימוקס [\[12:27\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=747s) א' זה נורא מסובך על הדבר הזה ואין לו שום דוקומנטציה טובה מה שאומר שזה המון מאמץ לכתוב פריורק הזה עכשיו היכולות הם כמעט בלתי מוגבלות לכן ההבדל בין הפריורקים האלה זה כמות היכולות שהם חוספים לא רק הז אם בפרורק אללה כולם עושים בערך את אותם יכולות אלה עושים סט שונה של יכולות כל אחת בגלל שזה לוקח סמן לחשוב על יכולות שכדאי לממש אני אתן לכם דוגמה בטמוק אסולטור אפשר להחליף [\[13:00\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=780s) התנהגות של כל פונקציה prיטפליק b רק מעט מאוד מהפונקציות בדוט framework עצמו ברמת הCLRl אני לא זוכר את השם שלו כרגע MSI >> MSI רק במsליפ DL יש שם מעט מאוד פונקציות שטימו מחליף אבל הסיבה הייתה זאת אומרת יכולנו בגדול להחליט שכל הסטרינגים במערכת מאותו רגע מחזירים את האות A יכולנו אבל תחשבו שלכל סטרינג במערכת יש קולבק לבדוק מה כדאי לו להחזיר מה שאומר שהפרפורמנס נהיה מטורף מבחינת אז כל הטestטים הרבה יותר איתיים אז כסוג של בחירה בגיוון שזה נורא מסובך ואם אתה לא עובד בתוך מי מייקרוסופט נורא קשה לעשות את זה אז הייתה בחירה לעשות כמה שפחות מהטייפים האלה אז בגדול משנה כמה מהדברים שלפיילioioo [\[13:52\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=832s) שלסטםפיל ושלט time אבל בגדול כל פיwורק אחר כל דלילל אחר אתם יכולים להחליף כל התנהגות הוא סוג של היתק לtייפo ליתר דיוק חברת טלריק היא לקוח של טייפו הייתה לקוח של טייפו עד שהם החליטו לייצר טקט מדויק זאת אומרת ברמת מת הDL איך הסתכלנו על הדברים האלה זה היה מאוד מאוד מעניין להסתכל ולהגיד אוקיי זה סוג של מחמא אבל זה גם היה די מעצבן והם יצאו עם משהו שגם דומה בI ויש להם את אותם יכולות מבחינת האנדרליין [\[14:27\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=867s) אבל מכיוון שהם חיים הרבה פחות זמן הם עברו פחות לקוחות אז הם מימשו פחות פיצ'רים לאט לאט הם עוברים על עוד ועוד פיצ'רים לדוגמה עד לפני כמה חודשים אם רצית להשתלט על אובייקט שעוד לא נוצר על ההתנהגות של אובי קים שעושים להם ניו בתוך הפרודקש קול אז רק טימוק יודע לעשות את זה היום ג'סמו גם יודע לעשות את זה אז לאט לאט הוא מסיג בעות ועוד יכולות ההבדל במחירים ככל שזכור לי 800 דולר לליסנס 400 דולר לליסנס שתבינו את ה את הדברים האלה [\[14:58\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=898s) מצד שני טקו הוא קיים בערך שמונה שנים עכשיו והוא עבר אלפי אלפי לקוחות עם לגסיקוד פשוט נוראית אם אתם חושבים שהלגסיקוד שלכם מפחיד אז אני אומר לכם שהוא לא רע בכלל יחסית ג'סמו קיימים בערך שנתם וזה באמת גם ההבדל מבחינת הפיצ'רים ms זה פרויקט שהתחיל מבחור בשם פלי שפעם לא עבד במייקרוסופט ויצר פרימוק בשם MbUnit משום שמעל MbUnit ובחור מאוד חכם מאוד מאוד נחמד ואז הוא התחיל לעבוד במייקרוסופטarch [\[15:29\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=929s) לפני בערך שלוש שנים אני והCEO של טייפיטמוק נסענו לרדמונד כדי לבקר את החבר'ה של מייקרוסופט שם ולהראות להם את טייפיט בגלל שהיה איזשהו דיון אולי כדאי שטייטמוק יישולב בתוך סטודיו בגלל שהוא נורא עוזר לטestינג של SharePoint מייקרוסופט נורא נורא רצה לדחוף את שרפט באותו זמן ובין השאר גם יצא לנו לפגוש את פלי והחבר'ה שלו ם יצאו באותו זמן כלי שנקרא פקס מישהו שמע על פקס פקס מג'נרד testים הוא מסתכל על הפאס של הקוד שלך ומג'נרט testים שעוברים על כל הפא זאת אומרת כל הרange casesס תחשבו על זה ככה זאת אומרת הוא הוא הוא הוא תוספת נחמדה ליוניטestים אחרי שכבר יש לך ‏testing הוסיפו עוד מלאק [\[16:13\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=973s) Test בינטגרש ויש לכם אחלה [coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)") ואז בין השרנו את זה לחבר'ה של פקס והנה שלושה שבועות אחרי זה הם יצאו עם כלי שנקרא [Moles](https://osherove.com/blog/2010/5/25/justmock-and-moles-a-short-overview-for-tdd-alpha-geeks.html "JustMock and Moles – A short overview for TDD alpha geeks (osherove.com)") מולס משתמש בפרופיילר API כדי לעשות פייק לכל דבר הוא עובד באותה באותו באותו רעיון של הפרופילר API אבל API שלו אחר לגמרי ונוראי אבל הוא עובד על אותו רעיון אז שתבינו טג הייתה די חלוץ ואז אז וואלה אנשים התחילו להשתמש באותו רעיון זה הסוג של אגוטריפ מבחינתנו אבל גם נורא התעצבנו כי זה אומר שגם טייפ לא נכנס לויזל סטודיו בסוף אמ [\[16:51\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1011s) עכשיו במס הכלי הזה הוא חינמי ובעצם סטודיו 2012 Moles נקרא מייקרוסופט בגרסה הבאה שלio יש לכם את הדבר הזה build in והוא משתמש בפרופי API והוא מאפשר לכם לעשות חיק כמעט לכל דבר כל אלסטם time בגלל שחבר'ה עובדים בתוך מייקרוסופט יש להם גישה לעשות קוד יותר מסובך מבחינת המימו של הפרופיילר API יש להם יותר ידע אז הם הצליחו איתם אפשר למרש כמעט כל דבר עכשיו מבחינת הזabity של הפיורק הוא מאוד גרוע כרגע עד שהabילity הזה לא ישופר לא הייתי ממניס להשתמש בדבר הזה אבל שווה בהחלט להסתכל על זה כי הגישה שלהם מבקי היד היא שונה לגמרי מבחינת שני הדברים האחרים הגישה שלהם היא שלכל קלאס שיש לך במערכת הם מג'נרטים לך קלאס אחר [\[17:38\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1058s) שעליו אתה יכול לעשות delegגטatס לכל פונקציה ובדלגס אתה אומר על הפונקציה איך להתנהל אז אתה צריך ללכת לכל פונקציה ולהגיד הפונקציה הזאת היא delגate שזורג אספש פונציה הזאת היא דלגטיר שלוש מבחינת מטן זה מאוד בעייתי אבל הכוח הוא כוח מאוד מאוד חזק אני עדיין לא אוהב את הAPI הזה אבל אין ספק שהם עשו פה משהו שהולך לעזור להמון מפתחים להתמודד עם לגסי בצורה מאוד מאוד טובה המיטבילטי יכול להיות שהוא שהמחיר שישנו הוא קצת גבוה כרגע לכן לכן אני עדיין לא ממליץ להשתמש בדבר הזה למרות שהוא חינמי. [\[18:12\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1092s) אני מקווה שיעשו בזה הרבה שינויים כדי שבגרסה הבאה זה כבר יהיה יותר טוב. אבל מה שמעניין זה שלדוגמה במולס מולס בעיקר נועד כדי שתוכל לכתוב testים בפקס כדי שפקס שהוא נתקל בדברים בפס שמשתמש בפייל סיסטם אז תוכל לעשות פה פייק אוטומטית. מולס בדרך כלל לא נועד לעשות וריפיקציות אז במולז אין פי שמשהו נקרא במולז אתה לא יכול לעשות אתה יכול לכתוב הסרט משלך תכתוב delגט שעושהפג לטרו שמה שהוא נקרא אבל אין very verifיפקש [\[18:43\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1123s) אי אפשר לעשות דברים לביס classes זאת אומרת מבחינת לגסיקוד עדיין חלק מהיכולות הם לא חוספים אז צריך להבין שהיום אם עובדים עם לגסיק הדבר הזה פחות מתאים למרות שהוא מתאים ל לדברים שיסיים לא רק שאלות לגבי הרבה ההבדלים בין הפרמוקים האלה זה חשוב מאוד שכשבאים לבחור framewor מבינים אם זה conסטרrain או uncוstrain הנקסטרrain נותנים לכם את היכולת לבחור את הדיזיין שלכם הקונסטרra לא נותנים לכם יכולת [\[19:13\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1153s) כי בקונסטרrain זה אומר שאתם יכולים אך ורק להחליף מימוש של פונקציות שאפשר לממש בעצמכם אז זה חייב להיות וירטואלי חייב להיות nonסal אסור שזה יהיה סטטי לדוגמה אסור שזה יהיה prvטate ‏protected אולי כי אפשר לרשת מהקס צריך להיות כדי לממש את הפונקציה בעצמכם אז מבחינת הדיזיין של איך הקוד צריך להיראות הפריורקים האלה במידה מסוימת בגלל הקומפייר מכתיבים לכם איך הדיזיין שלכם צריך להיראות כדי שתוכלו לעשות טestינג זה לא בהכרח דבר טוב [\[19:43\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1183s) לפעמים זה בסדר לפעמים לא זה לא אבל אסור לתת לפרורקים האלה לקבוע את הדיזיין כולו אתם צריכים לדעת דיזיין טוב בלי קשר לפרוורקים האלה אתם יכולים לעשותפרורק שהוא מאוד testable אבל הדיזי עדיין יהיה גרוע בסדר מבחינת הזביליות שלו אולי testable אבל לא בהכרחable הפרוקים האלה נותנים לכם את היכולת לבחור הם נותנים גם את מה שאלה נותנים לעשות פייק לאינטרפייס וכולי אבל אם יש לך משהו שהוא סטטי הם מאפשרים לך להשתלט עליו גם וזה באמת ההבדל ביניהם לכן והם עולים כסף בגלל שנורא מסובך לממש אותם דבר אחד שלא עולה כסף זה מוז אבל מוז לא נותן את כל היכולות שצריך בדרך כלל בלגסות [\[20:24\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1224s) אוקיי אז בוא נראה אני אראה לכם את הטestטים עכשיו עם חלק מהפריים האלה ואחרי זה גם עם טיפרקסטו ו ואז אנחנו נראה לי נעשה הפסקת צהריים אז אם עד עכשיו כתבנו את לפני הטestטים של לוגog שקורה לקרוא ללוגר או לקרוא לובוב סרביס לוגoger זה רק אפtion כן, [\[20:55\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1255s) ככה זה נכתב בNITס, למרות שאסור לנו להשתמש בזה. זה הדוגמה הכי בסיסית לפרו שמייצר משהו בצורה דינמית. זה משהו שהוא בלילט בניט, לא מומלץ להשתמש בו, אבל נורא נחמד להסתכל עליו כסוג של learning experience, לראות את האבולוציה של הפרימוקים האלה לאורך זמן. אז בIT Moקס כדי ליצור פיקר לא צריך ליצור קלאס משלך. אתה יוצר דבר שנקרא דינam. למרות שהדינamמיק מוק יכול להיות גם סטב מילה מוק היא מאוד מאוד קיימת בכל השכבות האלה אתה אומר לו איזה טייפ לממש איזה טייפ לרשת ממנו [\[21:32\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1292s) ואז אתה אומר לו תשמעט שפונקציה רס תקרא עם הטקסט הזה בסדר >> אז תשימו לב גם שזה סוג של equals אין פה אז אי אפשר אי אפשר להגיד על הפרמטרים סוג של קונסטרינטים חשובים או לא חשובים זה כמו הסרט אז אני אומר לו expectect ואז אני מייצר את הlogin manager with איך אני עושה את זה אני נותן לוק log הזה שיצרתי מהדינam אני נותן לו יש לו propery שנקרא mo instance שמחזיר object [\[22:12\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1332s) אבל מה שיפה זה שכשאני עושה לו cט לilלגר ברט timeים בצורה קסומה זה פשוט יעבוד הוא יתאים לאיילוג כי בעצם הקוד הזה מקפל בנטיים קוד שיורש מאיילוג ואז במוקס אני אקבל את הדבר הזה שנראה כמו אבל כל פעם שקוראים לפונקציה שלו הוא בסך הכל שומר את הול ואז בסוף אני אומר verifיפי פה הverיפי הולך לכל הדברים שעשיתי להם אקפקט קודם פה לדוגמה ועושה אסרט על כל אחד ואחד מהם שזה נקרא [\[22:50\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1370s) אז ברמה מסוימת זה ממש נחמד זה חסך לי את העבודה של הכתיבה של כל הקלאס הזה ובאמת כשיו מוקס היה אחד הפרמוקים היחידים מלבד עוד דברים כמו eyמוק שאנחנו אפילו לא נראה פה אז באמת היה התקדמות לעומת כתיבה של הדברים האלה בצורה ידנית הנה הנה הדרך לכתוב את זה עם מוק וסטאב אני יוצר דינam מוק שלer דינam מ שלice ואני אומר ללגר expect and throw בקריאה לר ‏new loger exception [\[23:23\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1403s) כאשר כאשר אתה מקבל את הפרמטר שנמצא בזאת. בסדר? אז בעצם מה שאני אומר לו כשמישהו קורא כשמישהו קורא לפונקציה right עם פרמטר תזרוק את האקספtion. אך ורק אז הוא יזרוק את זה. אין לי דרך להגיד לו תזרוק את זה לא משנה מה. אין לי דרך להגיד לו תזרוק את זה אם יש y בתוך הסטרי. זרוק את זה אך ורק עם הסטרינ שווה ליו אז אם מחר יש לי הרבה אינפוטים אני צריך להוסיף expect throw לכל אחד מהם [\[23:54\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1434s) אבל זה לא רק expect throw זה גם throw וזה גם expect זאת אומרת אני גם אשתמש בזה כסב אבל כשאני אקרא לverיפי הוא גם יעשה על זה הסט תשימו לבעיה פה אני משתמש בסטאב שלי גם כמו בטest הזה לא אכפת לי אני לא הנה זה המקובקט שלי אני אומר לו expectect לר עםג exception אחלה מצוין הבעיה היא שיש לי פה גם מוקס [\[24:36\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1476s) אבל כשאני עושה verיפי מה שיצרתי זה בעצם שני מ objects בטest הזה ופעם זה זה די היה הסטנדרט שכל דבר שהוא פייק הוא היה גם מוקט פעם הסטנדרט היה תעשה וריפיי לכל מה שיכולת בגלל שאתה יכול. היום זה הרבה יותר מובן שזה לא רעיון כזה מדהים אבל פעם לא היו את הפרטיס. אנשים היו צריכים ללמוד בדרך הקשה גם אני למדתי את זה בדרך הקשה. פעם גם אני הייתי עושה את זה. היום אני יודע אם יש לי יותר ממוק או obקט אחד אני לא רוצה לעשות את הדברים האלה אז אני אף פעם לא עשה וריפיי על הכל אני תמיד עשה וריפיי על משהו ספציפי אבל בוקס אין לי שום יכולת כזאת יש גם עוד בעיות של maintainity פה right כתוב כסטריק מחר אני משנה את השם של הפונקציה אני צריך ללכת לשנות את כל הטestטים אני לא יכול לעשותקטורים [\[25:19\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1519s) אז בעיה של מטן גם שאלות לגבי זה אוקיי איך הדברים האלה נראים ברימוקס? עכשיו דברים נראים קצת יותר נחמד. אם אתה רוצה לייצר fake iloger אתה אומר mo repositorygenate יש לי גם generate [stub](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1 "Introducing stubs (The Art of Unit Testing, 2nd ed., ch. 3)") של i loger מה שאני מקבל חזרה זה אין לי איזה משהו שעליו אני אשלח propפרerטy מאתחיל את הlogגin maner with ישר עם המקל loger שלי [\[25:52\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1552s) שימו לב אין לי פה expectect אין לי פה שום דבר כזה יש לי בסוף mlog assert was cold ואז יש לי פה lדה express אני אומר בינתן logger עכשיו הloger פה פה זה תמיד יהיה השם של הדבר הפייק פה. זאת אומרת הם לא צריכים להיות באותו שם אבל זה תמיד תייחס לאותו אובייקט ביןגר כלשהו שהוא שזה שזה הפייק שאתה מייצג אז זה היה צריך לקרות logger. עם הפרמטרים האלה עכשיו תשימו לב זה arang וסט בדיוק כמו שעשינו קודם בניס זה היה arange אבל הפק היה חלק מהר אז כדי להבין מה יש ביפי היית צריך ללכת עוד פעם לתחילת הטest כדי להבין הרange והסט ברמה הזאת הוא הרבה יותר נחמד דווקא הפרורק הראשון שיצא מסוג של הרange אט לא היה רינוקס היה מוק [Moq](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5 "Current isolation frameworks for .NET (The Art of Unit Testing, 2nd ed., ch. 5)") [\[26:42\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1602s) אה ארינוקס היה אם אני לא טועה הראשון שוריד את צורך לכתובנגים בשם של הפונקציה. תשימו לב שאין לי פה שום strיingנ בשם של הפונקציה. יש לי פה לנדה expppression ואז אני יכול לעשות loger. נק. אז מה שנחמד זה שאם אני עושה refacoring לרשם לשם אחר, כל הטestטים שלי גם משתנים אוטומטית. מבחינת מטן זה הרבה יותר חזק. זה הAPI האחרון של RS. יש ל עוד שני API שנורא קל להתבלבל באיזה להשתמש בכל שלב. [\[27:15\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1635s) זאת אחת הסיבות שאני לא מאמץ להשתמש בו. הנה פה זה הטestט השני. עוד פעם אני רוצה לעשות פייק לאילוג ואני רוצה שהוא יזרוק exception. אז אני יכול להגיד לו stלog expect. שים לו שק מרגיש כמו משהו שאני אעשה לו verifיפט שלי אחרי זה יהיה רק על פונקציה אחת. תכף נסתכל עליו. אוקיי סליחה אז expect loger right ואז נקודה thr [\[27:47\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1667s) New ler reception יש פה עוד משהו שהשתנה תשימו לב שהapi עכשיו הוא יותר fluent expectect מחזיר לי את אותו אובייקט ואז אני אומר נקודה throw אין לי פה שתי קריות נפרדות או expectected throw אז כאשר מישהו קורא לoger right yo אז תעשה throw לoger exception יש לי גם את היכולת להשתמש בargument matס אוקסטרים על הארגומנטים ולהגיד כל דבר או אך ורק חלק מהדברים זה גם אחד הדברים שרינו מוקס הציג יחסית מוקדם >> אפשר שאלה >> כן >> אה הסטוס כל כאילו קורה אחר כך אם אני קראתי לו כמה פענים הוא שומר את כל אחת מהקריות שלי כדי לדעת מה קרה >> כן הוא שומר את כל הקריות שהיו קודם ולכן אחד הדברים שרינו מוקס גם עשה יפה זה שהוא בניגוד לnitס הוא nonןסטקט [\[28:35\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1715s) פעם הוא היה סטריקט אבל גם זה השתנהט מס אומר שאם אמרת לו שהוא מצפה אז הוא מצפה רק פעם אחת בגרסאות היחסית חדשות של כל הפרימוקים הם כולם נוסטריקט מה שאומר אתה אומר לו זה היה צריך לקרות אבל לא אכפת לי אם קראו דברים אחרים ולכן הם שומרים את כל הלוג של הקריאות ואם זה קרה אפילו באחד מהם זה פשוט עובר אז מבחינת מינabity אם מחר הוספת עוד שתי קריאות שלא אכפת לך מהם הטסט לא נשבר בסטריקט מוקס בדרך כלל שוברים את הטestינג מאוד בקלות אז testסט הם מאוד סטריגי לך ישר כן [\[29:10\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1750s) אז גם פה assert was called servr עם exception גם אם קראו לסרס עוד 13 פעמים לפני זה וגם חמש פעמים אחרי זה בעבר זה קרה פעם אחת ולכן זה מה שחשוב >> והטר קורה ברגע >> סליחה >> קורה ברגע שזה קורה >> הרו >> כן >> הרו קורה כן בדיוק שזה כשראי הרו קורה כשהשורה הזאת רצה הוא קורה כשהשורה הזאת רצה >> שאלה >> כן >> יו זה אין ‏string במקרה הזה >> לא יו זה לא any string יו זה אקטס string במקרה הזה אני תכפר לכם קונסטרנטים אבל אני לא רוצה לבלבל אתכם עכשיו עם של קונסטרנטים ברינו כי אני לא רוצה שתשתמשו ברנו [\[29:48\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1788s) אני אציג לכם את זה במוק אני אראה לכם את הקונסטרנט אבל יש פה את הap שאתה יכול להגיד לא אכפת לי איזה סטרים נשלח גם באסרט וגם ב בסטאפ בקפ >> הדפולט הוא כאילו exact >> הדפט הוא אז exact בפריורקים האלה אתם תראו שבטפem הדפט הוא דווקא הפך בטyוק הדפט שלא אכפת לו מהסרים ששלחת אלא אם כן אמרת לו שזה אקז וזה אחד הדברים שטייטמו הוא יחסית שונה שהבנו שבדרך כלל רוב המקרים לא אכפת לך מה אתה שולח אתה תמיד רוצה את ההתנהגות הזאת למשך הטקסט דווקא ציפיתי שעד עכשיו רוב הפרימוכים כבר יבינו את זה אבל אה זה עדיין לא פעמים [\[30:25\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1825s) עוד שאלות אוקיי >> אם יש שבקט מסובך בפונקציה אם זה לא הנקודה right string אלא נקודה right מקבל עכשיו איזשהו אינסטנס >> כן איך אנחנו אנחנו צריכים עכשיו לעשות סטאב מזה איך אנחנו להשבות אותו כאילו זה הולך יותר מסובך אז זה הולך להיות יותר מסובך ואני אראה איך איך עושים את זה וגם יהיה לכם תרגיל שאתם צריכים לצפות שהוא קיבל אובייקט עם פרerטז מסוימים >> אוקיי >> אבל בדרך כלל מה שקורה זה שיש argument mature שאומר קיבלת למדה של אובייקט שנראה ככה ואז אתה אומר שהאובייקט נקודה propפרery שווה שווה אבל שם זה כבר מתחיל להיות מסובך ושם כבר עדיף לכתוב handen [\[31:03\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1863s) כי הטest יתחיל להיות בלתי קרי אז אנחנו נגיע יהיה גם לזה. טוב, בואו נעבור חזר למוק ונראה את ההבדלים. הדברים האלה לא הפטנו כרגע. אוקיי, אז זה הטest הראשון במוק. אני מייצר מוק של ב-Moq אין את המילה. הכל נקרא מוק, שזה אחד הדברים שמפריעים לי. אחזות שאני לא כל כך אוהבת מוק זה שעדיין מבחינת הAPI אין את ההבנה שבדרך כלל אתה לא צריך מוקט. [\[31:34\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1894s) אין אין בכלל את ההפרדה ביניהם. אז אני אבל מה שאני מקבל בעצם זה לאגר אלא מוק של מוק שלגר זה אומר עם קונטרולר כזה שבו אתה תעשה עליו verifיפי אחרי זה תגיד לו את ההתנהגות אבל כדי לקבל את הפק objectט עצמו יש לו propפרy שנקרא object פה log object מהבחינה הזאת זה דומה לMO instance שהיה ב-NUnit mo אז הobect פה ההבדל הוא שזה לא object זה i loger בגלל שאני משתמש בגנenקס הבחינה הזאת זה יותר נחמד, לא צריך לעשות custing וכולי [\[32:08\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1928s) אני אומר is login אוקי ואז אני עושה verifיפי תשימו לב עכשיו verifיפי ופה כבר יש פה קסטרrain אז אני ניתי בכוונה דוגמה של כמה מכוער זה יכול להיות לא בגלל מוקס זה מכוער בגלל זה יהיה מכוער לא משנה מה אם יהיה לכם יותר מדבר אחד verifיפי ותשימו לב אני אין לי פה expectect יש לי verify logr ואם אני רוצה לבדוק פרמטר אני יכול להגיד it is of string ואז יש לי פה למדה ואני יכול להגיד שהstring [\[32:38\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=1958s) A וsting conts b זה כל זה לפרמטר הראשון כי אם יש לי שני פרמטרים לבדוק יהיה לי עוד שורה כזאת אני חייב לכתוב שורה פרמטר אם יש לי קונסטר ואז אני יכול גם לכתוב שזה נקרא לאפס פעמים אומס at list בדרך כלל אני ממניץ לא להשתמש בפרמטר הזה בכלל ואז הוא עושה כן [\[33:20\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=2000s) למה זה שיניתי בגלל ששיניתי את הtest אמרתי times never עכשיו מן הסתם אתם רואים שהטest הזה נכשל אין כאן שומר לי dude you just broke it הדוגמה של ה עכשיו עוד דברים ש אה תכף נראה יש עוד כמה דברים במוק שהיום זה יש כמה סיבות שהיום אני לא ממליץ להשתמש במוק למרות שהמון אנשים עדיין משתמשים בו כי הוא הרבה יותר טוב מבחינת היוטity מרן אומ אנחנו נראה שמבחינת יוזבילטity יש כבר היום דברים שלדעתי יותר טובים כבר ממוק אז הגיע הזמן להתקדם קצת הלאה [\[33:52\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=2032s) הנה הטest עם מוק וסטאב קיצור סטאב לogג ביצירת מוק של אילוגר שימו לב כמה זה מתחיל לבלבל עכשיו אבל עכשיו אני אומר לו ככה התנהגות setup אין פה כבר את המילה expפק שזה כבר טוב setup וינתן x מה זה x זה תמיד הפיק אקט שלך אם מישהו קרא ל x right יכולתי גם לכתוב פה לogתו פה משה זה לא משנה אוקיי זה סתם למדה אקפר אבל זה תמיד זה קצת עדיין מבלבל רוב האנשים שרואים את זה בפעם הראשונה לא מבינים שמה שאני כותב פה מתייחס לפייק objectקט שאני אשלח [\[34:28\]](https://www.youtube.com/watch?v=bguE7d1AL7A&t=2068s) צריך להתרגל לזה והנה אתם ‏Eh ## Related - [Why use isolation frameworks?](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec1) · The Art of Unit Testing, 2nd ed., ch. 5 Why use isolation frameworks, the starting question of this lesson before it rewrites the handwritten fakes. - [Constrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev2sec1) · The Art of Unit Testing, 2nd ed., ch. 6 Book section on constrained frameworks, the group the lesson places Rhino Mocks, Moq, FakeItEasy and NSubstitute in. - [Current isolation frameworks for .NET](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5) · The Art of Unit Testing, 2nd ed., ch. 5 Surveys current isolation frameworks for .NET, the same set the lesson compares. - [Fifteen things I look for in an Isolation framework](https://osherove.com/blog/2013/11/23/fifteen-things-i-look-for-in-an-isolation-framework.html) · osherove.com Roy's checklist for isolation frameworks, starting with strict versus non-strict defaults, which the lesson demonstrates. - [Isolation frameworks – lessons from the wild](https://osherove.com/blog/2008/12/3/isolation-frameworks-lessons-from-the-wild.html) · osherove.com Lessons from teaching the major .NET isolation frameworks side by side, as this lesson does. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Defining isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5#sigil_toc_id_99), ch. 5 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 #### The Art of Unit Testing, 2nd ed. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Constrained and unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1), ch. 6 - [First steps with NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3), ch. 2 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 - [Interaction testing using mock objects](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4), ch. 4 - [More NUnit attributes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec6), ch. 2 - [Introducing stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1), ch. 3 #### osherove.com - [The future of Isolation frameworks, and how Moq isn't it (for now)](https://osherove.com/blog/2012/6/27/the-future-of-isolation-frameworks-and-how-moq-isnt-it-for-n.html) - [FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition?](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html) - [Minimizing unit Test Fragility – 8 features in Typemock Isolator to help](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html) - [JustMock and Moles – A short overview for TDD alpha geeks](https://osherove.com/blog/2010/5/25/justmock-and-moles-a-short-overview-for-tdd-alpha-geeks.html) - [Test Coverage and testing angles](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html) [Previous lesson Mocks and Stubs](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/mocks-and-stubs/) [Next lesson Advanced Mocks and Stubs](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/advanced-mocks-and-stubs/) --- title: "Advanced Mocks and Stubs" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/advanced-mocks-and-stubs.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/advanced-mocks-and-stubs/" tags: [] author: "Roy Osherove" description: "Lesson 10 of 22 in TDD in .NET in Hebrew (Day 2 - Mock Objects and TDD), 12:50. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Advanced Mocks and Stubs 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 2 - Mock Objects and TDD Lesson 10 of 22 Duration: 12:50 [Watch on YouTube](https://www.youtube.com/watch?v=2fAcLl60UeQ) Spoken in Hebrew ## In this lesson Roy Osherove continues with [Moq](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5 "Current isolation frameworks for .NET (The Art of Unit Testing, 2nd ed., ch. 5)"), showing callbacks, Verifiable and VerifyAll, and overriding protected methods, and warns that verifying many interactions you do not care about is [overspecification](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Avoid overspecification (The Art of Unit Testing, 3rd ed., ch. 8)"), explained with a story about sending his son to buy pizza. He then writes the same logger tests with [FakeItEasy](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html "FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition? (osherove.com)"), whose API starts with A and whose error messages he finds better than Moq's, and with NSubstitute, and recommends starting with one of the newer frameworks. Asked about [profiler-based frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)"), he says they run slower but are used to get [coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)") on [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") [before refactoring](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_225 "Writing integration tests before refactoring (The Art of Unit Testing, 3rd ed., ch. 12)"). ## Transcript 1,803 words [\[00:03\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=3s) הloger שנקרא לו x אם מישהו קורא right in is any string אז תזרוק exception תיצור m service תשלח את הסog object ואת הm service object לקrctטור ואז תעשה verify שבנתן הסice שימו לב אני אומר על המקרice verify service verify service service right exception אז יכולתי גם להגיד ‏right it is any string ואז העיקר שהוא נקרא הטest הזה היה עובר כן [\[00:35\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=35s) >> האובייקט שאתה מעביר שם ללמדה זה יכול להיות כל אובייקט נכון זה לא אובייקט מה שאני אומר פה זה סתם אקספרש הפרמטר כאילו שאתה נותן ללמדה לפני החץ זה יכול להיות כל אובייקט זה כל שם זה לא זה לא אובייקט הsvc פה לא קיים בשום מקום אחר SVC לא קיים תעשה אני עושה פשיט 7 אתה תראה שהוא לא נוצר בשום מקום אחר הוא לא קיים בטסט הזה זה סתם שם זה declarative אם אני >> איך הוא יודע שיש לזהר right כאילו זה השאלה >> מכיוון שזה מכיוון שהמוקסרס [\[01:08\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=68s) הואגנריק זה [מוק](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") שלי הבנתי >> זה מה שגורם לו לדעת שיש >> כאילו יוצר קוד ברגע תסתכל על החתימה תראה שזה void mo של iw service >> אוקיי >> ומה שהוא מקבל זה system link expression system action של servicי שמכיר זה דלגate שמקבל אtשן שיש לו פרמטר אחד מסוג ובסרביס אוקיי יש לי עוד שאלה מספר [\[01:38\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=98s) כאילו הדבר שנראה לי הכי פשוט אם היה זה הייתי אומר כל פעם שנקרא right תריץ אתניסגate שני כותב כאן ובו הייתי כותב איפה אתה באמת ארוע הדבר הזה אז כאילו ממש להחליף ממש להחליף את הפונקציה >> כן בכל בכל הטסט בכל הפקים החדשים יש את היכולת לתת קבק שפה אתה עושה את המימוש האחר לפעמים זה רעיון לא רע לפעמים זה יותר פשוט מאשר לעשות הבריכה קריק אנחנו דינים לקרוק שרט שר >> זה זה יותר קרי אם אף פעם לא כתבת טestטים ככה ברגע שאתה רגיל לראות את הטestטים ככה אז הרבה יותר קל לראות את זה באסרט למטה מאשר לראות הסרטים באמצע הטסט וואו איזה ריח טוב אבל לפעמים [\[02:17\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=137s) אין שום ברירה ובאמת חייבים לעשות callק אז אני יכול להגיד במקום אני יכול להגיד פה callבק ופה אני מקבל פשוט אני יכול לעשות פה מה שאני רוצה לזרוק אספtion תחזיר שלוש מה שזה לא יהיה ופה אני יכול גם לכתוב הסרטל עכשיו הנה פה יש עוד כמה קטג'ים יש API במוק שמאפשר לך לעשות כזה דבר לא רק שזה frow גם תעשה לזה בסוף נקודה verifyable מהיפיable אומר [\[02:48\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=168s) יפיבל אומר אולי בסוף אני ארצה לעשות על זה גם וריפי תשמור את המידע הזה ככה בשביל בשביל הכיף בשבילי ואז אני לא חייב לעשות m servicy אני גם יכול לעשות ככה service verify או verify all verify all הולך על כל הverifyable שהיו לי קודם ועושה להם מתי בדרך כלל תראו verifyable כשיש לכם multipl [\[03:20\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=200s) Object בדרך כלל מבין אז בדרך כלל אם אתם רואים verifyable זה אומר שבדרך כלל משהו לא טוב הולך לקרות יהיה בדרך כלל וריפייבל יש יותר מאחד זה אומר שיהיה לכם אתם עושים מסרט על הרבה אינטראקציות בדרך שלא אכפת לכם בכלל זה סתם [סטאב](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") מה אכפת לכם שמשהו קורה >> אבל זה היה סכום >> מה >> זה היה לך עושה למוקסרביס למרות שזה היה >> יכול להיות מוקר לא משנה >> אוקיי >> אסטבלוג סליחה >> זאת אחת הסיבות שאני אוהב לתת שמות למשתנה [\[03:52\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=232s) אם אני רואה פה וואלה stל verifיפיי כבר אני יודע שאני לכתחילה לא הייתי אמור לעשות וריפיי לדבר הזה אבל כשאני מסתכל על טסטים הדבר הראשון שאני מסתכל וואלה אני רואה פה שני verifיפיי כבר לא כבר בעיה לפעמים אני סתם רואה veryיפי all ואז אני מחפש וואלה יש לך פה שלושה verifיפיable אבל מה אכפת לך שבדרך הוא קרה למשהו העיקר שקיבלת את הריז בגדול תחשבו על זה אם יש לי הרבה וריפיable בדרך הדרך שאני חושב על זה זה תחשבו אני שולח את הבן שלי לקנות לי פיצה בסדר הוא כבר בן 5 וחצי הוא כבר די גדול אני שולח אותו לסוף הרחוב נותן לו 100 ש₪ ואומר לו לך לסוף הרחוב תנה לי פיצה אתה תבקש שיהיה ככה גם פטריות וגם זה אבל אתה צריך להגיד לו בהתחלה שלום אדוני המוכר בן של רועי כרגיל אני רוצה את הפיצה הזאת תודה ואז נעבור שעתיים הבן שלי חוזר אולי מוקה וחבול אולי הוא חוזר הביתה ואתה יודע אבל הוא חוזר עם הפיצה ביד והוא אומר אבא היקר אני הבאתי לך את הפיצה אני במקום מסתכל על הפיצה אני מתקשר למוכר אומר לו תגיד הגיע לך איזה ילד בן 5 וחצי האם הוא אמר לך בדיוק את המילים האלה [\[04:52\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=292s) הוא לא אמר את המילים האלה ואז הוא לוקח את הפיצה של הבן של זורק אותם לפעמים אני אומר לא אכפת לי אז זה מה שאני עושה במקום שיהיה אכפת לי מהדריזט אכפת לי איך קיבלתי אותם והטestטים כשאתם משתמשים בוריפיable ובכלל על אינטראקציות שלא אכפת לכם זה מה שאתם עושים הט שלכם יתחיל לבכות לכם כל פעם ששיניתם משהו באינטרנal impלמנש במקום שאכפת לכם מהריזלט שלכם יגיד אבל אמרת שזה יקר ככה וזה יקרה ככה לא אכפת לנו אז אם אני רואה verifיפיable בדרך כלל זה סימן לא פה [\[05:24\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=324s) בסדר בסדר? אנחנו נראה אנחנו נעשה קצת טest רוwז אולי מחר אולי היום נראה איך הדברים ילכו ואתם תראו שהדברים האלה קורים די הרבה דווקא ועוד פעם קורים בגלל שככה אנשים היו רגילים לעשות את זה בגלל שפעם זה היה נחשב בסדר אמ אני גם יכול גם עם הפריורקים האלה גם עםוקס אני יכול לעשות overriד את דברים עם methodס זאת אומרת אם יש לי פה פונקציה שהיא [\[05:56\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=356s) אני יכול לעשות over לפונקציה הזאת בטestים שלי כל זמן שהיא אוed או public אני יכול להגיד protected set up to l verify שימו לב ואז אני עושה verify שזה באמת נקרא אם זה פאליק הייתי יכול לעשות פשוט verifיפי על publicקוד איך שהייתי רוצה אבל פה בדברים האלה בורטל metodס אני אראה אני לכם ממש לעשות את זה בצורה ידנית ואני אלמד אותכם איך לעשות את זה גם בהמשך היום. [\[06:35\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=395s) עכשיו בואו נראה את הפריורקים הקצת יותר חדשים. [FakeItEasy](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html "FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition? (osherove.com)"). FakeItEasy זה framewor. עוד פעם זה constrain framework אני אוהב את השם שלו. מה שנחמד בו זה שהכל מתחיל באות A מבחינת הAPI. אני רוצה לצר פיקלגר אני אומר A. ‏IOG קיבלתי חברה אני שולח אותו ללגן manager with more אני אומר אני רוצה לעשות ver אני אומר A call 2 שימו לב יש פה אין פה שום פרמטר אני פשוט משתמש ביק ישירות to fake cite with string ignored must happen [\[07:08\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=428s) יאלה חמוד נכון מה שנקרא לקחת את זה עד הסוף שימו לב איזה פשטות איזה סוג של אלגנטיות יש פה וזה אחד הדברים שאני אוהב בפרמורקים האלה, הפשטות הזאת האלגנטיות. דרך אגב, עוד דבר מאוד טוב בפרמורקים שהם לא מ שהerור מessage שלהם הרבה יותר טובים. כשהטest נכשל ציפית לזה אבל קיבלת משהו אחר. הארורים במוק היום הם די גרועים. וא צריך לכם קצת להרגיש את זה. הארורים בפיק ובין subבסיט מה שאנחנו נראה הם ממש טובים. [\[07:40\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=460s) נורא אכפת להם היובליות של הדברים. הנה הטestטים מוק וסטאב. תיצור אפיק אילוגר. תיצור fake i web service ואז אתה רוצה לעשות שver אז אתה אומר call to fake logger right with a string ignored throws new loger exception מצוין ואז אני מייצר את הlogin manager with m and st לא לא מה שהתכמנתי ואז אני בסוף אומר to fake web service with a string that [\[08:13\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=493s) Contains got exception בסדר זה גם זה מתחיל להיות קצת קצת ארוך מדי אבל זה יותר קרי מהלמד אקספרש שלנו קודם אוקיי שאלות מדליק לא אוקיי אז FakeItEasy הוא באמת אחד מהפרwים שאני ממש ממש אוהב גם בגלל שיש לוle point of entry אבל [NSubstitute](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5 "Current isolation frameworks for .NET (The Art of Unit Testing, 2nd ed., ch. 5)") הוא הפריורק השני שאני גם בדdיל קבתי גם אותו הוא ממש ממש נחמד. [\[08:47\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=527s) תשימו לב דרך אגב לגבי API פה אין פה את המילה מוק ואין פה את המילה stב הכל נקרא פק שאולי בגלל זה זה קצת מקל עלינו באסבסט גם אין את המילה stב יש רק subבסט שזה כמו לקרוא לזה פייק אני רוצה ליצור את logger אני אומר substitute for ilogger אני רוצה ליצור את הlogin manגר אני שולח לו את הake logger ואני אומר ככה הake received קריאה לri is string שהוא contains ככה וככה אין פה גם את הלנדה אקרש אני פשוט אומר שמשהו res [\[09:21\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=561s) ואז ואז מה שאני מקבל זה משהו שנראה כמו אני פשוט קורא לו את הפונקציה כמו שהייתי קורא לה קודם איפה אני כן צריך למדוט אם אני רוצה לעשות argument constr אז גם פה הapi ממש ממש חמוד וחכם הנה דוגמה לapi שיש לי וסב substitute for i web service substitute לiloger fake ‏loger loger right עם r string אז do [\[09:51\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=591s) Th new exception לדוגמה אני גם יכול להגיד לו פה פשוט אין לו פלא שכחתי אני חושב שהם פשוט הורידו את הרו הזה אז פשוט תזרוק איזשהו exceptפtion ואז תיצור את הake service ואז תגיד received right in עם any str אם אני רוצה לעשות conסate יותר מארגומנט אחד זה עוד שורה יש לך ארפל אגומנטס בסדר אז יש לך זה לא עוד שורה זה עוד פסיק ועוד ארגומנט [\[10:30\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=630s) אז תשימו לב איזה הבדלים בAPI יש פה אבל בכולם יש את אותם יכולות עוד לא עברנו על דברים חוטי כמו קייס או לאטור וכולי אנחנו נעבור עליהם אחרי ארוחת צהריים מה שנעשה גם אחרי חת צהריים אנחנו גם נמשיך את ה את התרגילים איפה שתראו את המילה מוק אתם יכולים לבחור איזה שאתם רוצים מבחינתי FakeItEasy substitute או FakeItEasy אוסב איזה שאתם רוצים בסדר אני לא מסנשברים אתם יכולים שנש במוק אם אתם רוצים אני ממליץ כבר להתחיל עם אחד מהחדשים כי אני מאמין שהם העתקיד של הפמוקים היום יש להם יחסית מעט משתמשים כשכתבתי את הספר שלי למוק היו מעט מאוד משתמשים גם וריינו מוקס היה ככה ומוק היה ככה מבחינת ה השאלון שעשיתי הסקר שעשיתי היום זה בדיוק ככה למוק [\[11:15\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=675s) ולפריורקים החדשים האלה אבל אני חושב שהפרוקים האלה בהחלט מייצגים את לאן אנחנו הולכים וכולי שאלות שהיית לא שאל שאל >> ברוב חברות שהיית חשוב בסוג של הפרופיילינג או בסוג של הפרוקסיז >> ברוב משתמשים בפרוקסיז כי הפרופיילינג עונים הרבה כסף אבל בחברות שמשמשים בפרופיילר ללגסי קוד הם בדרך כלל אומרים שאין תחליף לדברים האלה וזה נכון הרפקטור שצריך לעשות לגסיק בדברים של פרופיילינג הוא כמעט בלתי אפשרי לעשות אז זה דרך טובה מאוד לקבל [coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)") ואחרי זה לעשות פקטור [\[11:59\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=719s) מבחינת הביטויים הפרופיילר מול האלה שבים על פרוקסי יש כאילו הבדל גדול >> יש הבדל די גדול זה בדרך כלל יכול לקחת v2 מבחינת הזמן של האקסקיושן שלס >> וזה עדיין זה עדיין מתאים כאילו לtd למשל >> כן כן זה מתאים זה תראה בטייפוק היה לנו כמה אלפי טestטים טובים על הפריימורק של הAPI וכולי לקח להם כמה דקות טובות לרוץ אבל זה עדיין השתמשנו בזה לא הרצנו אלפים אבל הרצנו 1000 טסטים בדרך כלל שהיינו כותבים [\[12:29\]](https://www.youtube.com/watch?v=2fAcLl60UeQ&t=749s) כל רבע שעה או חצי שעה היינו מריצים את כל הטסט ככה ליתר ביטחון כל פעם שהינו עושים קומית גם ככה היה לנוקסגרש שהיה לנו אומר לנו אחרי חמש דקות מה קורה זה לא היה כזה נורא בכלל אבל באמת הם כולם רצו בזיכרון אבל הפרופיילינג בהחלט לוקח יותר זמן. אוקיי? אז בתיאבון ניפגש עוד חצי שעה. ## Related - [Internal behavior overspecification with mocks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8) · The Art of Unit Testing, 3rd ed., ch. 8 Book section on internal behavior overspecification with mocks, the problem behind the pizza story. - [FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition?](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html) · osherove.com Roy weighs FakeItEasy against NSubstitute, the two newer frameworks the lesson shows and recommends. - [The future of Isolation frameworks, and how Moq isn't it (for now)](https://osherove.com/blog/2012/6/27/the-future-of-isolation-frameworks-and-how-moq-isnt-it-for-n.html) · osherove.com Explains why Roy sees Moq as the past, backing the advice to start with a newer framework. - [Advantages and traps of isolation frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec6) · The Art of Unit Testing, 2nd ed., ch. 5 Advantages and traps of isolation frameworks, including over-verifying, as seen with Moq's Verifiable and VerifyAll. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Writing integration tests before refactoring](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_225), ch. 12 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 #### The Art of Unit Testing, 2nd ed. - [Current isolation frameworks for .NET](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5), ch. 5 - [Constrained and unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1), ch. 6 #### osherove.com - [Test Coverage and testing angles](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html) [Previous lesson Isolation Frameworks](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/isolation-frameworks/) [Next lesson Recursive Fakes](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/recursive-fakes/) --- title: "Recursive Fakes" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/recursive-fakes.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/recursive-fakes/" tags: [] author: "Roy Osherove" description: "Lesson 11 of 22 in TDD in .NET in Hebrew (Day 2 - Mock Objects and TDD), 3:10. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Recursive Fakes 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 2 - Mock Objects and TDD Lesson 11 of 22 Duration: 3:10 [Watch on YouTube](https://www.youtube.com/watch?v=l-dwbnVu_qc) Spoken in Hebrew ## In this lesson With [NSubstitute](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html "FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition? (osherove.com)"), Roy Osherove shows [recursive fakes](https://osherove.com/blog/2008/10/4/isolator-feature-focus-recursive-fakes.html "Isolator feature focus: Recursive Fakes (osherove.com)"): when a person object is faked, its manager property returns a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") as well, instead of each returned object being set up on its own line. He says [Isolator](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html "Minimizing unit Test Fragility – 8 features in Typemock Isolator to help (osherove.com)") was the first framework to do this and that it makes tests more [maintainable](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)"), because a new property or method that returns an object is faked by default. He then sends the group back to the exercises, up to the login manager that uses a static method. ## Transcript 367 words [\[00:07\]](https://www.youtube.com/watch?v=l-dwbnVu_qc&t=7s) מה שאני יכול לקבל אוטומטית זה person שהמנדר שלו הוא גם פיק בלי לעשות את זה בשתי שורות זאת אומרת אם פעם רציתי שגם פרו נקודה מנגר אם רציתי שפה מנג'ר יהיה [פייק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") הייתי צריך להגיד אם הייתי רוצה להגיד ככה, אם הייתי רוצה בוא כבר לא זוכר את הAPI כבר מתבלבל אה נכון when נכון [\[00:38\]](https://www.youtube.com/watch?v=l-dwbnVu_qc&t=38s) פעם אם הייתי רוצה להגיד ככה P when manג'ר אה זה propפרerטy נכון אפילו לא צריך לעשות ספון מצטער שאני מבלבל אתכם פשוט אני לא רגיל לעבוד באמצע הפסידות בדרך כלל פיק זי אבל רציתי לעשות אם אני אעשה p manager לעשות aserט is not או [\[01:19\]](https://www.youtube.com/watch?v=l-dwbnVu_qc&t=79s) מה שאני אמור לקבל פה זה שמנגר בי default הוא לא נעל ברגע שאני יש לי סבסיט לפרסם ותשימו לב שגם מנג'ר מקדם מנג'ר גם לא ינן גם המנג'ר שלו לא יובל פעם בטestטים לכל לכל פרופרטי או פונקציה שמחזירה אובייקט ורציתי שהוא יהיה פייק הייתי צריך להגדיר את זה בשורה היום הנושא של recקury fיקס הוא אחד הדברים השולטים הפרימוקט הראשון שעשה את זה דרך אגב היה אסוליטור והרעיון היה שאם יש לך משהו שכבר מחזיר אובייקט והot objectט שלך הוא פייק [\[01:51\]](https://www.youtube.com/watch?v=l-dwbnVu_qc&t=111s) אז אז כל הרט object שלו הם [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") by default ואז הest הרבה יותר [maintainable](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec2 "Writing maintainable tests (The Art of Unit Testing, 2nd ed., ch. 8)") אחרת אם מחר אני מוסיף עוד פרטי שלא אכפת לי ממנו בטestינג אבל מישהו משתמש בו אני צריך להגיד שהוא פ כדי שהוא יחזיר איזשהו ערך אחרת הטestטים הישנים של אולי הם פשוט מכשלים ככה by default ברגע שאני עושה substitute for person אז כל דבר שאפשר לעשות לו פיק הוא fake ואז אני יכול או לשנות את ההתנהגות שלו או שבדfaultט הוא פשוט [stub](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") שמחזיר default vales זה החלק היפה שבשורה אחת אני אומר person אכפת לי ממנו אבל כל מה שפסון מחזיר לא אכפת לי עד שעד עד שיוכל אחרת ואם מחר יש לי פרפרטי חדש או פונקציה חדשה שמחזירה אובייקט עדיף אותם f ולא יקרה שום דבר אם מישהו יקרה להם אם מישהו יקרא להם את [\[02:39\]](https://www.youtube.com/watch?v=l-dwbnVu_qc&t=159s) מה שאני מבקשת לעשות עכשיו זה שתמשיכו את ה את הז כולל maner 2 ולעשות את הCIז עד login manager with static זאת אומרת כשאתם מגיעים לפה לעצור ופה אנחנו נלמד עוד טכניקות בסדר אז להמשיך בבקשה את התרגילים עד מספר שמונה כולל שאלות דרך אגב שאלה ‏Ja. ## Related - [Isolator feature focus: Recursive Fakes](https://osherove.com/blog/2008/10/4/isolator-feature-focus-recursive-fakes.html) · osherove.com Roy's post on Isolator's recursive fakes, the feature the lesson shows with NSubstitute and credits to Isolator. - [Fake chains: stubs that produce mocks or other stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec6) · The Art of Unit Testing, 2nd ed., ch. 4 Fake chains: stubs that produce other stubs, the repetitive setup recursive fakes remove. - [Features supporting future-proofing and usability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 6 Book section on isolation framework features for future-proofing and usability, the maintainability benefit claimed here. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8), ch. 8 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 #### The Art of Unit Testing, 2nd ed. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 - [Writing maintainable tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec2), ch. 8 #### osherove.com - [FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition?](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html) - [Minimizing unit Test Fragility – 8 features in Typemock Isolator to help](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html) [Previous lesson Advanced Mocks and Stubs](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/advanced-mocks-and-stubs/) [Next lesson Legacy Refactoring intro](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/legacy-refactoring-intro/) --- title: "Legacy Refactoring intro" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/legacy-refactoring-intro.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/legacy-refactoring-intro/" tags: [] author: "Roy Osherove" description: "Lesson 12 of 22 in TDD in .NET in Hebrew (Day 2 - Legacy Code Tools), 16:23. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Legacy Refactoring intro 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 2 - Legacy Code Tools Lesson 12 of 22 Duration: 16:23 [Watch on YouTube](https://www.youtube.com/watch?v=agS3I0yEUc8) Spoken in Hebrew ## In this lesson Roy Osherove turns to dependencies that cannot be injected through a constructor, such as a call to a static logger, and introduces [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") from [Michael Feathers'](https://osherove.com/blog/2009/8/18/ndc-video-michael-feathers-working-effectively-with-legacy-c.html "NDC Video – Michael Feathers – Working Effectively with Legacy Code (osherove.com)") book [Working Effectively with Legacy Code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226 "Read Michael Feathers’ book on legacy code (The Art of Unit Testing, 3rd ed., ch. 12)"), which he recommends. He moves the call into a protected virtual method with no logic and has a [testable subclass](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95 "Partial mocks (The Art of Unit Testing, 3rd ed., ch. 4)") of the login manager override it and save the text in a public field for the test to check, noting that in real [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") he would first have an [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)") in place. To concerns about exposing such methods he answers with internal methods and [InternalsVisibleTo](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6 "Overcoming the encapsulation problem (The Art of Unit Testing, 2nd ed., ch. 3)"). ## Transcript 1,933 words [\[00:03\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=3s) אתה יודע שזה מה שיש לך להגיד למה testing is good testing נכון רדג אתה רוצה להגיד מה שמצן [\[00:38\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=38s) טוב בואו נסתכל על logic פה אנחנו נכנסים קצת לדומיין שקצת רגע סיכוי ואנחנו נדבר על איך לעשות רפקטורים לקוד כדי שנוכל לכתוב אותו עם פריורקים שהם קונסטר כי לפעמים הדיזיין הוא כן משהו שהם רוצים לשנות אז אנחנו הולכים לראות בקורס הזה גם טכניקות של ריפקטורים כדי שנוכל שנות קוד קיים וגם טכניקות בלי ריפאקטורים. אז היום היום בעיקר נלמד על טכניקות של ריפקטור. עכשיו במקרה הזה בתרגילים שאתם יכולים לעשות עכשיו יהיה לנו כמה סוגים שלפנency שאנחנו נצטריך להתגבר עליהם. [\[01:13\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=73s) הסוג הראשון של dependency זה dependency static במקרה הזה אחת הדרישות יהיו בoger static יש קרי לstatic logger right אין logger אין קונסטר פה בעצם גם מה שעשינו עד עכשיו אנחנו עשינו מה שנקרא constructor inction לקחנו dependen ועשינו להם inקטור constructor יש הרבה סוגים של inctionקש שאפשר לעשותקסטור זה אחת הדרכים הבסיסיות בגלל שזה לא אופציות [\[01:43\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=103s) אבל פה אין בכלל מאיפה לעשות in עכשיו השתלה איך אנחנו יכולים לוודא שatic logo r באמת נקרא נניח יש לי פה באג שחסר לי פהספיס או יש לי באג וחסר לי פה איזשהו מידע מאוד חשוב איך אני יכול להוכיח בטest שהמידע הזה חסר אז הדרך שאנחנו נראה עכשיו נקראת extract and over היא נלקחת מספר שאני ממליץ עליו בחום שנקרא [Working Effectively with Legacy Code](https://osherove.com/blog/2005/4/15/book-of-the-month-working-effectively-with-legacy-code.html "[Book of the month] Working effectively with legacy code (osherove.com)") יש לכם אותו פה [\[02:14\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=134s) תקנו אותו פשוט ככה שמייקל פדרס הוא שווה את המשקל שלו בזהב מבחינתי המון מהדברים שאני למדתי על ריפאקטורינג למדתי מהספר הזה יש בו הרבה יותר דברים ממה שאנחנו נלמד בקורס אבל בגדול הספר הזה מדבר על מה קורה כשאתה בעולם שבו וודקה זה פתרון מאוד טוב לבעיות גסי שלך שפל וסלב התלהבו מהצלו דווקא בסדר הזה ויש יש שם המון המון חוכמה המון סוגים של ריפקטורים באמת ספר ספר נורא מעניין. המון מהדוגמאות הם ב-C++ ובג'אבה, אבל זה עדיין אף ספר מאוד קרי. [\[02:48\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=168s) אחת הד אחד הטכניקות הכי הכי פשוטות היא נקראת אקסטרct ואיד והרעיון הוא ככה. אם אין אם יש לנו depפendנסי ישיר ואנחנו לא יכולים להחליף אותו ישירות אז אנחנו נעשה שכבת אבסטרקציה קטנה מעל ואנבדוק שהשכבת אבסטרקציה נקראה. אבל במקום לעשות פה קלאס אנחנו נעשה אבטרקציה רק למתודה לקריאה למתודה. במקום לוודא שatic loger right נקרא אני אעשה לו אact method [\[03:28\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=208s) ולמטודה אני יכול לקרוא call the logoer אני לא רוצה לעשות אותו statטיק אני רוצה לעשות אותו וירטואלית וtectד במקרה שלנו אוקיי אז זה בעצם מה שאני אקבל היא עדיין לא תהיה מספיק טובה בגלל ש יש פה את הסטרינג הזה מבחינתי מה שאני הולך לעשות זה בטestטים שלי אני הולך להרשת מהקלאס הנוכחי [\[03:58\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=238s) למרות שזה הקלאס שאני בודק ולעשות אורייד רק לפונקציה הזאת אז ככה שכל שאר הקוד עדיין יעבוד אבל הפונקציה הזאת יהיה להover ואז אני בעצם אתגבר על הדפנenנy אבל אני לא אני רוצה גם לבדוק את ‏string אז אם אני אעשה over strיing אני לא יוכל לבדוק אותו צריך לקבל את כל המידע בפרמטר אז אני אעשה פה contנטרול altפct paramet te ועכשיו מה שיש לי זה cologer עם login requested בעצם הפונקציה [\[04:30\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=270s) היא טיפשה לחלוטין אין לה שום מידע אבל לא שיניתי את הפונקציונליות של הקוד הפונקציונליות עדיין עושה בדיוק אותו דבר ההבדל היחיד הוא שעשיתי את הקוד יותר testable עכשיו שימו לב שבמקרה הזה בגלל שזה לגסוד הצד הראשון שלי הוא לעשות ריפקטורing הוא לא לכתוב test בלגסי קוד אמיתי לא הייתי עושה את הרפקטור הזה אפילו בלי שהיה לי אינטגרש test אחד רציני פות שעובר דרך הדבר הזה בדרך כלל שניים אבל כשיש את הנטגרation test אני יכול להתחיל לעשות את הדבר הזה [\[05:05\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=305s) אז עשיתי פה exract method עשיתי את המתprcted virtual ופה אני מוודא שאין שום לוגיקה וזה הקוד הכי טיפה שיכול להיות כי אם יש לי פה לוגיקה מכיוון שאני הולך לעשות לה אורייד בטestטים שלי לא יהיה לי שום סיכוי לבדוק אותה אז אם יש פה באג אני בחיים לא אמצא אותו אז עכשיו הנחת יסודי שאם כל דלוגoger נקרא אז הלוגר נקרא בגלל שהקוד הזה כזה פשוט אני יכול להרשות לעצמי להניח את זה בטestים אני אצור קלאס חדש ונקרא לו testableגog [\[05:44\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=344s) ‏manager with stat והוא יורש לי login manager stat אוקיי תשימו לב אני יורש מהקלא שאני הולך לבדוק אבל במקום לעשות פייק לכל הקלאס אני הולך לעשות בעצם פיק אבריד רק לפונקציה אחת אז זה פיקד מבחינתנו אוקיי הדבר הבא אני יכול לעשות overri לכל ואני לא רוצה לקרוא לבי b כי בעצם זה הדפendנency שלי אם אני אקרא להסטיקלג אז יהיה לי את אותם בעיות שהי גם קודם אולי זה יקח הרבה זמן אולי זה יזרוק את הבאג שהיה גם קודם אז כל מה שאני עושה עכשיו זה כמעט מה שעשיתי בפיק לוגoger הנר שכתבתי אני אכתוב [\[06:30\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=390s) שטקסט אל create fieldד נעשה אותו publicק וזהו עכשיו את הטestטים שלי אני אכתוב כנגד הקלאס הזה כל שאר הקוד בקס הזה הוא producion cod בגלל זה תשימו לב זה לא נקרא [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") זה נקרא testable זה מאוד חשוב כי זה testable verion של אותו clס אחרי זה אני יכול לכתוב test שנראה ככה [\[07:01\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=421s) Test is login senario ‏Cold calls static loger עכשיו כתבתי statטיק loger פה בשביל הדמו אתם אצלכם לא תכתבו שהלוגר הוא סטטיק אף אחד לא אכפת שהלוגר הוא סטטיק בוא סיכון שתכתבו לoger מכירה הלוגר הוא סטטיק אבל במקום ליצור את האנסט של הקלאס האמיתי אני אכתוב [\[07:34\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=454s) פה מכיוון שאני יוצר אותו ישירות אני יכול לקצר את השורה ולהגיד זה כבר עכשיו אין לי מה לעשות פה להשתמש בטest בisolation framewor או כל דבר אחר אני פשוט יכול להגיד lm is login ו string assert conסני אוקיי וm [\[08:05\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=485s) לא טס בדיוק כמו שעשינו עם הפייקל בהתחלה שהטest הזה יעבור סימן שהסטיקל נקרא אז הרפקטינג שעשיתי הוא לקחת קריאה לסטאטיק סו אה בסדר אי אפשר לזמור את הדלת >> שניה >> אוקיי חבר'ה תתרגזוזר רק עוד שתי דקות אתם הולכים לכתוב קוד תחסיקו מעמד אוקיי [\[08:37\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=517s) זה מרגיש יש למוכון של מונטיפ אז כל מה שעשיתי זה ללכת ללוגog manager ולהגיד protected virtual הקוד עצמו עושה בדיוק את אותו דבר זה נקרא אrct and over שאלות לגבי אני שבק בתוך הבית שלסטיק >> אני לא קורא לו אז מה אכפת לי אתה קורא לו >> תראה לסטטיקלגר יהיו טסים משלו היוט הור שלנו לא קשור אליו כרגע כי אין לנו שליטה עליו ‏static lower אתה צריך להניח שיהיה לא טסים משלו וגם test שלך זה באג בסטיקל כנראה שיהיה בוא נניח ככה אבל בשביל זה החברה שלו גם עושים [\[09:16\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=556s) בסדרסים >> אין בעל שזה יותרנו עד קוד לתחלק כלומר כל הדבר הזה בשביל קירת מתודה אחת אם יש לנו הרבה מתודות כאלה זה >> נפח את הקוד בצורה >> זה נראה כזה יוצר הרבה קוד אבל הקוד הזה הוא מאוד מאוד פשוט אחרי שימוש זה בקוד לגסי אמיתי, אחד הדברים שאתה תגלה שהטכניקה הזאת היא מאוד חזקה ומאוד פשוטה. היא הרבה יותר קלה ממה שעשינו עד עכשיו כי היא לא מחייבת אותך ליצור אינטרפייס חדש במערכת היא לא מחייבת אותך לממש את האינטרפייס הזה היא לא מחבת אותך לעשותק היא פשוט עושה אקסטר לאיט פשוט עושה אקסטר ואחרי שתי שניות יש לך את הקוד הזה ותשים לב כמה הקוד הזה פשוט [\[09:59\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=599s) הוא דווקא ממש לא מסובך יש לי פה שהמטוריות הרמנית רק לפרויקט של הטסטים ש אני לא אוכל לראות אותם ממקום אחר >> שאני לא אוכל לראות אותם ממקום אחר את >> כל תלכ כל דלוגר לתוך שלא יהיה מצב שאני מישהו יקרא לזה בטעות שלא כאילו מפחיד אותך שיקראו לפונקציות האלה בטעות זה >> זאת אומרת אצלכם לא עושים קוד >> גם אם עושים זה לא >> אז איך אז לא יתסו את זה אתה חושב >> בר שיש הרבה כאלה זה בעיה [\[10:30\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=630s) זה בעיה לעשות קוד ריבו אם יש הרבה כאלה >> לא אבל קוד ריבו זה לא פתרון לכל דבר בקוד של אז יש תמיד סיכוי שמישהו יקרא >> כן אבל שיש >> בואו נגיד חבר'ה אני יכול ברפלקשן לקרוא לכל מתודה prvט שיצרתם מ פעם יש סיכוי שאני אעשה את זה לא משנה איך הפ שלכם יר >> לא אבל זה גם שנגיד אם אני משתמש באובייקט ואני רואה את הפאבליק מת שלו אז אני אראה כמה שפחות שאני לא אתזה 400 >> המתודה הזאת היא טקט היא לא פאבליק חשוב שתזכור את זה נכון >> נכון עכשיו סתם גם בתור דוגמה בג'אבה כל הדברים מביא את שואל בדפולט [\[11:13\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=673s) מה אנשים עושים בעולם הג'אבה משתמשים רק >> צריך להבין שבדרך כלל ואם אנחנו נסתכל ועוד פעם זה יותר שיש שקשור לדיזיין אוקיי אם תחפשו נושא של solוליד אתם תראו שקסים שהם extendable extensible זה אחד הדברים שהם דווקא כן מוסיפים דיזין מבחינת התמישות שלו. אמ אבל מבחינתנו אם אנחנו באמת רוצים, מכיוון שאין פה דת, זה לא שאני מאמין שזאת הדרך הכי טובה, זאת דרך שלא צריך להיות לכם בעיה איתה. [\[11:50\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=710s) אבל אם יש לכם בעיה איתה, תמיד אפשר לעשות if the bug. אתם מכירים את הפ? אז תעשו ותעשוט או private זה נגמר העניין. זאת אומרת אתם יכולים להגיד אנטרנal גם על מתודות אתם יכולים להגיד [InternalsVisibleTo](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6 "Overcoming the encapsulation problem (The Art of Unit Testing, 2nd ed., ch. 3)") על הtest assembly אם אתם מכירים את הנושא הזה אני אסביר אדed [\[12:24\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=744s) Internal אוקיי אם עשית את זה interטרנal אז כביכול אף אחד לא יראה את זה אבל אז אני יכול ללכת לאassemly infו שלי אה בוא נראה איפה איפו זה פה אני יכול להוסיף InternalsVisibleTo ואני יכול לתת פה את השם של הtest assembly אז מאותו רגע מבחינת הtest assembly זה פליט אבל מבחינת כל אחד אחר זה prיבט [\[12:54\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=774s) אוקיי אז זה משהו שעושים כשבאמת יש בעיה עם לחסוף את הדברים אני אישית אין לי שום בעיה עם הדבר הזה זה איזשהו פחד אחד בגלל שזה בסדר, זה בסדר שזה מפחיד, אבל אני אומר לכם שמבחינת השימוש בעולם האמיתי אנשים לא עושים בביוז לדברים האלה במיוחד שזה הכל באותה חברה אם הייתם עושים איזה פריורק שאתם עושים דליבר ואנשים עושים לו ומשתמשים בו ועושים לו אוברייד וכל מיני דברים כאלה מילא פה זה הכל קונטינט בתוך חברה אחת יש לכם כאילו באותה מידה שאתם מוודאים שלכל פרמטר מתחיל באות A אם אתם מצליחים לעשות את זה אז אין שום סיבה שלא תצליחו גם לבדוק את הנושא הזה בוא נפת ככה וגם זה באמת מבחינתי זה די שטויות אבל אם צריך אפשר למצוא דרך לפתור את זה [\[13:39\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=819s) אה עוד שאלות ואני גם יכול לעשות כן if ולעשות ככה prate protected בדרך כלל לא צריך לעשות את זה אוקיי אז זה הדבר הראשון עכשיו בוא נסתכל על עוד מקרה [\[14:17\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=857s) נלך ללגן man statס lws אוקיי אחרי זה יש לנו יהיה לכם יהיה לכם עוד דרישה לבדוק גם שסטיקוב סרביס נקרא כביכול זה נראה אותו דבר אבל בין השר יש פה גם את הדרישה שמשינם גם ישלח עכשיו משני nameים זה גם מכיוון שמשינם משתנה בין מכונה למכונה אז כל פעם שתריצו את הטest במכונה אחרת זה בעצם test אחר אז גם על משינם אנחנו נצטרך להתמודד איתו וזה גם זה עוד statטיק propפרerטy גם פה אפשר להשתמש באקסטרct ואover כדי לשלוט על המשי שלנו עוד פעם להוסיף את זה לtestable verion [\[14:57\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=897s) אמ עוד דברים חשובים חבר'ה אנחנו כשנגיע לזה אנחנו עוד מעט גם נפתור את נושא הזמן מה יקרה אם אני אבקש ממכם להוסיף את הurentate and time למage >> אותו דבר בזה לא >> מה >> אותו דבר >> כן זה משהו שכבר מתחיל להיות קצת בעייתי בשיטה הזאת אנחנו נדבר על עוד שיטות כשנגיע לתרגיל הזה אז מה שאני מבקש ש נעשה הפסקה בינתיים ז אומרת לא הפסקה אנחנו נתחיל לעבוד בינתיים [\[15:32\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=932s) כשתגיעו לתרגיל הזה staticס מה שאני מבקש שתעשו לי תרגיל ת ו10 אה וכשנגיע לתרגיל 11 תנסו לעשות אותו בעצמכם ואנחנו ניפגש פה נראה כמה זמן זה יקח אני מקווה שעוד חצי שעה כבר נוכל להיפגש פה עוד פעם אם יקח שעה יקח שעה זה גם בסדר אל תנסו למר יותר מדי חשוב שתלמדו בקצב שלכם זה שתנה אני אסתכל לראות מה הקצב כרגע לנסות לעשות את 9 10 ו1 ואז אנחנו נחזור וניפגש יש שאלות לפני זה [\[16:22\]](https://www.youtube.com/watch?v=agS3I0yEUc8&t=982s) אוקיי ‏Yeah. ## Related - [Mock Objects vs. "Inherit & Override"](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html) · osherove.com Discusses overriding a virtual method in a test subclass, the extract and override technique taught here. - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5) · The Art of Unit Testing, 2nd ed., ch. 3 Variations on refactoring techniques for breaking dependencies, in C#, alongside extract and override. - [Overcoming the encapsulation problem](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6) · The Art of Unit Testing, 2nd ed., ch. 3 Overcoming the encapsulation problem, the concern about exposing methods that the lesson answers with internal and InternalsVisibleTo. - [Read Michael Feathers’ book on legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226) · The Art of Unit Testing, 3rd ed., ch. 12 Recommends reading Michael Feathers' book on legacy code, the source of extract and override cited in the lesson. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Partial mocks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95), ch. 4 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 #### The Art of Unit Testing, 2nd ed. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 #### osherove.com - [NDC Video – Michael Feathers – Working Effectively with Legacy Code](https://osherove.com/blog/2009/8/18/ndc-video-michael-feathers-working-effectively-with-legacy-c.html) - [\[Book of the month\] Working effectively with legacy code](https://osherove.com/blog/2005/4/15/book-of-the-month-working-effectively-with-legacy-code.html) [Previous lesson Recursive Fakes](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/recursive-fakes/) [Next lesson Controlling Time](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/controlling-time/) --- title: "Controlling Time" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/controlling-time.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/controlling-time/" tags: [] author: "Roy Osherove" description: "Lesson 13 of 22 in TDD in .NET in Hebrew (Day 2 - Legacy Code Tools), 6:44. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Controlling Time 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 2 - Legacy Code Tools Lesson 13 of 22 Duration: 6:44 [Watch on YouTube](https://www.youtube.com/watch?v=cmaydKpLtJ4) Spoken in Hebrew ## In this lesson Roy Osherove applies [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") to the machine name as well, then explains why it does not suit time, which is used throughout a system. Instead he adds an API to a [central system time class](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec5 "Cross-cutting concerns injection (The Art of Unit Testing, 2nd ed., ch. 7)") so tests can set the current time, and resets it after each test because the change is static and affects other tests. He argues that a static class is not bad design in itself, suggests making the setter [internal and visible to the test assembly](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6 "Overcoming the encapsulation problem (The Art of Unit Testing, 2nd ed., ch. 3)"), and sends the group to implement it in the exercises. ## Transcript 683 words [\[00:04\]](https://www.youtube.com/watch?v=cmaydKpLtJ4&t=4s) אני רוצה קצת לדבר על הנושא של איך להכניס זמן ולשלוס לו זמן בטestטים שלנו כי דלת בבקשה >> אבל קודם כל אני אני אעבוד על הנושא של הכל ובסרביes אני קצת אראה את הכיוון קודם כל עשיתי אקסטרctט ועכשיו אני אעשה אקסטר גם למשינר שמת לב דרך אגב ברגע שעשיתם אקסטר פעם אחת כל שני נהיה די פשוט ברגע שהפטרן מובן אז פתאום אוקיי יאללה משינה עם עודual מט לא כזה נורא אז זה מטיק לא נורא מטו כן [\[00:44\]](https://www.youtube.com/watch?v=cmaydKpLtJ4&t=44s) אולי נעשה גט משימה name ככה שאני יכול לקצג את הlogin maner זה חשוב מאוד [\[01:17\]](https://www.youtube.com/watch?v=cmaydKpLtJ4&t=77s) Verion אף פעם לא עושה בשום דבר לדוגמה אני רוצה להגיד name will אוקיי עכשיו יכולתי גם את אותו דבר לעשות עם מזמן create field לעשות פה [\[01:50\]](https://www.youtube.com/watch?v=cmaydKpLtJ4&t=110s) שם יותר ש אוקיי אבל מה לגבי זמן לגבי זמן הנושא של אקסט לא כל כך מתאים כי זמן כמשהו שמשתמשים בו במערכת משתמשים בו בצורה רוכבית אז לעשות אקסטרד עכשיו בכל הקלאסים שמשתמשים בזמן יכול לקחת הרבה זמן אז במקום זה מה שנעשה זה נחשוב על פאטרן אחר. [\[02:21\]](https://www.youtube.com/watch?v=cmaydKpLtJ4&t=141s) אחד הדברים הכי בסיסיים שיש לכם כבר היום בדיזיין זה קלאס שנקרא time אז מה שהייתי רוצה לעשות בטסט שלי זה לכתוב ככה time אליי אני קורא לזה syיסטם time אצלכם זה יקרה time set new time [\[02:57\]](https://www.youtube.com/watch?v=cmaydKpLtJ4&t=177s) ובעצם מה שאני עושה פה אני מוסיף API מיוחד לטיים שלי במיוחד כדי שבטestטים שלי אני אוכל לשלוט בזמן מאותו רגע כל מי שמש בתים יהיה לו את הזמן שאני קבעתי אבל יש פה סכנה כי מן הסתם אני משפיע על טestטים אחרים אז כשאני משנה משהו במשהו ברמה סטטית אז אני צריך לעשות לו אנדו אחרי כל ‏public after test [\[03:28\]](https://www.youtube.com/watch?v=cmaydKpLtJ4&t=208s) לשמור שט כל מה שאני צריך זה להגיד syסם time reset ומאותו רגע הוא יחזור להחזיר את הD time now בדיוק כמו שהוא עשה קודם כל מה שיש לו זה איזשהו פלי עכשיו אם אני באמת מפחד שיגעו בזה וזה משהו שאני יכול לראות אולי למ שיפדו לגעת בו לעשות הנג אז אז אני את זה אני באמת עושה internal ו משתמש ב-InternalsVisibleTo לtest assembly שלי אז תשימו לב שה הפטר פה הוא שאני בכלל לא עושה inject שום dependency. [\[03:59\]](https://www.youtube.com/watch?v=cmaydKpLtJ4&t=239s) כל מה שאני עושה זה אני הולך למקום שבו גם ככה יש לי מקום מרכזי שממנו אני לוקח את ה-tיים דווקא בגלל שזה משהו כל כך מרכזי במערכת אז זה שזה סטטי לא אומר שזה דיזיין גרוע שימו לב אני פשוט הופך את הדיזיין לtestable ועל ידי זה שאני מוסיף איזשהו setר ורסט רק חשוב לא לשכוח לעשות את הטרדאן הזה בסוף כל אחד מהם שאלות את הסט >> מה >> איך מישמים את הסט >> את הסט זה יש מיליון דרכים ליישם את זה. [\[04:31\]](https://www.youtube.com/watch?v=cmaydKpLtJ4&t=271s) זה יכול להיות כן בהנחה שהדבר הזה היה בפרודקשן זה יכול להיות ברמה של פילד שהוא נלב זה יכול להיות ברמה של איזשהו פלאג כן [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") time שווה day time ומה אותו רגע [\[05:04\]](https://www.youtube.com/watch?v=cmaydKpLtJ4&t=304s) כן כן אפשר להגיד ישפ אפשר גם לעשות אותו ואז לבדוק אם הוא לא נעל ואז להחזיר את הטיים בדוק זה משנה העיקר שזה יעבוד משתמשים בקלאס הזה במקום כאילו בד time >> אצלך כבר יש את זה >> יש לכם קלאס שנקרא אתם לא צריכים לסוריס במקום אתם פשוט מוסיפים set לטלק מבחרים במ >> אפשר אולי לעשות אפילו כדי לאחוב את זה שאף אחד לא ישכח את ה אבל using דורש instance כלשהו כדי שתוכל לעשות לו dispose time by default הוא סוג שלו להמציא אסנס לצורך זה להמציא אסance ואיך והאינס הזה יעשה setט לזה ולעשות [\[05:43\]](https://www.youtube.com/watch?v=cmaydKpLtJ4&t=343s) אחלה מצוין אין שום בעיה מה שחשוב זה שהכדי לשלוט במשהו מרכזי אז פשוט מוסיפים למרכזי הזה יכולת להחליף את המידע שלו זה לא כזה נורא להפך זה אפילו מומלץ אם גם ככה כל המערכת משתמשת בזה אז אם אם לא כל המערכת משתמשת לזה אז מאותו רגע צריך לוודא שבכל המערכת בכל מקום שיוצים די פשוט משתמשים בטיים בסדר עוד משהו כשקוד רביו מאוד יכול לעזור פה דרך אגב אוקיי אני ממליץ בחום [\[06:14\]](https://www.youtube.com/watch?v=cmaydKpLtJ4&t=374s) אה שאלות לגבי זה אוקיי אמ אז מה שאני רוצה זה שבהתאם לטכניקה הזאת לכו תלמשו את את ה את הדרישה האחרונה של די טיים באמצעות הטכניקה הזאת תיצרו אצלכם את הקסטר הזה ואז תמשיכו גם לתרגילים של הogin manager with future בסדר ## Related - [Cross-cutting concerns injection](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec5) · The Art of Unit Testing, 2nd ed., ch. 7 Cross-cutting concerns injection, the settable central system-time approach the lesson builds for time used everywhere. - [Stubbing out time with parameter injection](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_64) · The Art of Unit Testing, 3rd ed., ch. 3 Stubbing out time with parameter injection, another way to control the current time in tests. ### Also linked in this lesson #### The Art of Unit Testing, 2nd ed. - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 - [Overcoming the encapsulation problem](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6), ch. 3 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 [Previous lesson Legacy Refactoring intro](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/legacy-refactoring-intro/) [Next lesson Working with Typemock Isolator](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/working-with-typemock-isolator/) --- title: "Working with Typemock Isolator" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/working-with-typemock-isolator.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/working-with-typemock-isolator/" tags: [] author: "Roy Osherove" description: "Lesson 14 of 22 in TDD in .NET in Hebrew (Day 2 - Legacy Code Tools), 26:41. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Working with Typemock Isolator 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 2 - Legacy Code Tools Lesson 14 of 22 Duration: 26:41 [Watch on YouTube](https://www.youtube.com/watch?v=vO-KpCDopU8) Spoken in Hebrew ## In this lesson Roy Osherove shows [Typemock Isolator](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html "Minimizing unit Test Fragility – 8 features in Typemock Isolator to help (osherove.com)"), a [profiler-based framework](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1 "Constrained and unconstrained frameworks (The Art of Unit Testing, 2nd ed., ch. 6)") for code that cannot be refactored: its API starts with Isolate, it can [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") any class, including ones with private constructors, and it verifies calls with any or exact arguments. He explains the Isolated attribute that cleans up static fakes after each test and the profiler environment variables that Visual Studio plugins and command-line runners set, as [Moles](https://osherove.com/blog/2010/5/25/justmock-and-moles-a-short-overview-for-tdd-alpha-geeks.html "JustMock and Moles – A short overview for TDD alpha geeks (osherove.com)") and JustMock also need. He then fakes static methods, future instances and non-public members without touching production code, mentions [SilverUnit](https://osherove.com/blog/2009/2/25/introducing-silverunit.html "Introducing SilverUnit (osherove.com)") and [CThru](https://osherove.com/blog/2009/2/25/adding-method-missing-support-to-vbnet-using-ctru-and-typemo.html "Adding Method-Missing support to VB.NET using CTru and Typemock Open-AOP (osherove.com)"), which he built on Isolator, and asks the group to test the original exercise code this way. ## Transcript 3,628 words [\[00:03\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=3s) מדהים מצחיק לא הופך את הפרודקש קוד למכואר מאוד אני קור לזה אקסטר ואבריט בגלל שנורא קל להתמכר לדבר הזה בכלל לא להוסיף אינטרפייסים לא שום דבר יצא לי לעבוד בכמה פרויקטים שבהם נכנסו ללגסי דודמות ופשוט דברים מה זה זרמו אקסטרקט ממש ממש היה כיף עכשיו לגסי עוד גם ככה לא מכוער אז יחסית אתה יודע כל כל קוץ במדבר פרח קוראים לזה עכשיו נדבר קצת על טמיסור מה קורה כשאי אפשר לשנות אתח קוד מה קורה כשלא רוצים או כשרוצים להוסיף פיצ'ר חדש [\[00:35\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=35s) על על גבי קוד קיים שאין לו testים במקרה כזה אי אפשר לעשות refacctטורing עם הקוד עם אגration test פופ כלים או profיילר bas כמו [Isolator](https://osherove.com/blog/2006/9/27/using-typemock-vs-design-for-testability.html "Using TypeMock vs. Design for testability (osherove.com)") נכנסים מאוד חזק לעבודה אבל קודם כל לפני שנתחיל עם הלגסיקות נתחיל דווקא עם הAPI הכי בסיסי כי האיסוליטור כמו הפריים אחרים נותן גם את אותם דברים שדיברנו נו עליהם קודם אלה שני הטestטים הבסיסיים שדיברנו עליהם רק עם isolator. אז אם אם מדברים על design decisions אז בisolator [\[01:11\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=71s) בדומה ל [FakeItEasy](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html "FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition? (osherove.com)") הכל מתחיל באותה מילה תמיד זה מתחיל במילה isolate והרעיון הוא שאם אתה לא זוכר את הAPI תמיד מילהate זה הדבר הראשון שאתה יכול לחשוב עליו גם פה אין את המילים [מוק](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") [וסטאב](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") יש תמיד [פייק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") אבל הAPI שלו הוא מאוד מאוד חזק אלה המקרים הכי בסיסיים שינה משהו בכלל >> כן גם פחות רואים אצל >> אחלה [\[01:41\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=101s) בליפלקש בן אדם חייך בטלוויזיה בכל אז אם אני רוצה לייצר instance של [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") logger כל מה שאני עושה זה isolate fake instance שלoger שיש פה רמה אחת אקסטר של API כי בנוסף לפייק אפשר לעשות עוד הרבה דברים דווקא בגלל היכולות האלה אז זה משהו שב בהתחלה בapi תמיד שוכחים לעשות isolate fake אילוגoger תמיד עושים וזה משהו שהוא עדיין לא אני חושב שבהחלט יכול להשתפר [\[02:13\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=133s) אמ אז בגדול אסוליטור הוא נוקד באותה גישה שהוא מחזיר לך ישר את האובייקט אבל בגלל שהוא גם לא משתמש בפרוקסי אז אפשר לעשות איתו הרבה יותר דברים לדוגמה לא אפשר לא רק לעשות פייק לאיילוגoger אפשר לעשות פייק לכל קלאס אפשר לעשות פייק גם לקלאסים שיש להם prrivateט conסטrucטור מה שאי אפשר לעשות עם הפוקסy framewמוקס שולחים את הakeer ואז הverיפיקציה היא בisolate. ‏by default יש שלושה דברים שאפשר לעשות or was called with any arguments or was called with exact arguments שזה מה שיש פה or was called with arguments [\[02:51\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=171s) Matching ששם אפשר לעשות את כל הguments שיכולנו לעשות עם האחרים עכשיו לטעמי הAPI שסיימנו איתו מבחינת המצרing של של הארגומנטים הוא לא נוח מספיק הוא אפילו מבלבל ב f take FakeItEasy ובendסבסיטute ובמוק האגum maters הם יותר טובים ואני חושב שזה משהו שאם הייתי יורד שם היום הייתי משנה ולכן בדרך כלל משתמש אך ורק ב was called with exact arguments or was called with any arguments [\[03:22\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=202s) ואני משאיר את האחרים ואני לא משתמש בהם בכלל >> אז סליחה אז מה מה אתה עושה לגביס string contטינס כאילו שאתה >> אז ככה לפעמים אני באמת משתמש בהם או שאני עושה את ה או שאני עושה אה את הדבר השני שזה נקרא isolate isolate when call שמקבל לדה ריקה ופה אני יכול לקחת כל object כולל live object [\[03:55\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=235s) זאת אומרת משהו שלא עשו לו פיק אפילו אבל פה זה יכול להיות fake i logger fake ioger right by default לאolator לא אכפת מהפרמטרים אז לא משנה מה אני אשלח פה אני יכול לשלוח נלד defaultט הוא הדפלט שלו זה any אני יכול להגיד do inadד זה לו את נקודה right [\[04:27\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=267s) אה יש פה will throw יש פה col orגנal למה יש פה מעניין יש פה אה יכול להיות שיש לי פה גרסה ישנה שאין עלי את הדסט בקיצור אני צריך להתקן את הגרסה שלי אבל בתרון יש לי פה דיןסד כמו שיש כל בט במוק שאני יכול לקחת את הפרמטרים ולעשות עליהם אסרטים ויפיים או לשמור אותם מאחר כך אני יכול זה מה שאני אוהב לעשות >> מה >> אני יכול לעשות את זה ל לפ ל לפ ל לפי זאת אומרת נגיד אם האינסטנס נוצר בתוך המתודה שאני בודק >> כן >> אני רוצה ש כאילו [\[05:02\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=302s) המתודה שאני בודק עושה ני למשהו ואני רוצה שהי שנוצר כשהוא קורא למתודה את זה >> כן אנחנו נראה את זה תכף אבל קודם נתחיל דווקא מהדברים הבסיסיים כי אחרי זה אנחנו נבנה על זה אז חשוב שתבינו את הI בסיסי אז יש לי fake instance קריאה וverify was call was call with any ופה אפשר לשלוח מה שרוצים עכשיו נראה את המקרה של מוק וstב אז אם אני רוצה לעשות stab loger שזורק exception אני אומר isolate when call fake looger right עוד פעם לא אכפת לי מהסטרים ‏will throw new logger exception אומר שזה מדבר בלשון עתיד [\[05:42\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=342s) ואז אני יכול לעשות verify was cod מדבר בלשון עבר fake servicיice right עוד פעם לא אכפת לו מהפרמטר זה הכי פשוט שבעולם שלחנו את שניהם בפרמטרים אין פה שום דבר שקשור ללגסי קוד אבל מה שיפה זה שאני יכול באותה מידה לעשות ככה רגע, לפני שאני ממשיך, יש משהו חשוב לגבי הנושא שזה בגלל שזה פרופיילר, אז יש כמה דברים שצריך לעשות שאי אפשר לעשות בפריורקים אחרים. [\[06:18\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=378s) יש פה אטריבט מיוחד שנקרא isolated. אפשר או לשים אותו על כל test או לשים אותו פעם אחת ברמת הtest fixure הisolated זה אטריבט מיוחד שבעצם עושה cleanupפ של הדברים הסטטיים שאנחנו הולכים לעשות. אם אנחנו אומרים לפונקציה סטטית מעכשיו להתנהג בצורה מסוימת אז היא תתנהג ככה עד סוף הפרocess אזated אומר לטפisolator שבסוף כל test ינקה את כל הבי ששמנו אז במקום שאני צריך לעשות down ולהגידור cleanup שזה עוד API שאפשר לעשות [\[06:56\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=416s) אז אפשר במקום זה פשוט לשים את האיולטed אם לא תשימו את זה יהיה לכם הרבה אפקטים שקשה מאוד להבין אותם. פתאום הטestטים יתחילו להתשל תבינו למה. עוד דבר חשוב כשמריצים את isolator. בגלל שהוא משתמש בפרופילר API, הפרייל API הוא לא enable by default. הוא לא enable by default. זה אומר שאם אני אסתם מריס את הטesting שלי הtypolור לא יעבוד. [\[07:27\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=447s) כדי שהפרופי יעבוד צריך להיות שני environment variables בococess שבו הפרופיילר עובד. זה יש שני שמות פשוט שמים להם x01 וגומרים עניין אבל צריך שזה יהיה את זה בזמן שהפרo רץ ואז הprofilers הם enable זה סוג של secקurity שיש בד defaultט וצריך להיות אדמניסטרטור כדי שהפרופיילרים ירוץו מה שאומר שהרבה פעמים אתם תצטרכו להריס את הטסטים בתור אדמיניסטרטור כדי לקבל את התוצאות האלה או לפחות בקונפיגורציה הראשונית [\[08:01\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=481s) במהלך ההתקנה בגלל זה כשמתקינים את Isolator אז הוא מתקין גם פגין בתוךסוד שבעצם כל התפקיד שלו רוב התפקיד שלו זה ש-Visual Studio ירוץ אוטומטית כבר עם הenvironment variables האלה enable ואז כשVisual Studio מתחיל את הtest processes אז גם אם זה MSTest או unit זה לא משנה באיזה test runer ty יותר עובד עם כולם לא אכפת לו הוא מוודא שהchesses גם יהיה להם את הvir [\[08:32\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=512s) אז אם אתם סתם תכתבו את הsmi שלטור ותנסו להריץ את ה-NUnit או את הIT command בלי הvirה כל הטestטים יקשלו אז אם מריצים את זה מתוך יש את הפגין שלator שברגע שהתקנתם זה כבר build in וזה פשוט יעבוד אם אתם מריצים את זה בקנדלי line בפסטור מגיע עם tmxl שכל מה שהוא עושה זה אתם נותנו את הקומנדל lineין של מה שהייתם רוצים להריץ בלי tx והוא פשוט מריץ את אותו דבר אבל עושה enable לinvement variable זה הטוב אז כל התפקיד שלו וככה אפשר להריץ את זה בקמנדל line בבילד וכולי [\[09:09\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=549s) עוד דברים חשובים זהו בד אלה הדברים שצריך לדעת בגלל שזה פרופיילר base אז אז חייב להיות varable דרך אגב זה גם אומר שאם אתם משתמשים ב-Moles אז גם צריך את הvement variabl האלה אז ב-Moles גם יש לו plugג לתוך studio וגם יש לו commנ מיוחד והוא צריך host אם אתם משתמשים ב-Visual Studio 2011 אז הוא צריך לעשות host process מיוחד בתוך אטריוט ודברים מאוד מוזרים כאלה כדי לקבל בדיוק את אותו אפקט גם [JustMock](https://osherove.com/blog/2010/5/25/justmock-and-moles-a-short-overview-for-tdd-alpha-geeks.html "JustMock and Moles – A short overview for TDD alpha geeks (osherove.com)") מטלריק [\[09:40\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=580s) יש לו את אותם conסנט שהוא צריךפגין ויש לו קומנדי מיוחד כדי להריץ את זה עם דברים אין פה שום שונה אבל זה תמיד משותף לכל הדברים האלה מה קורה אם אני רוצה לעבוד עם הלogי maner with statics אז כל מה שאני רוצה לעשות זה לבדוק שהלוגר שלי נקרא אז מה שאני יכול לעשות זה קודם כל להשתלט על כל המתודות הסטטיות של הלוגר. אם אני רוצה להתחיל לעקוב אחריהם, אני צריך להגיד לטימוק להתחיל לעקוב אחריהם. [\[10:14\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=614s) אז אני יכול להגיד ככה isolate fake static methods ואני יכול לתת לו או שם של classסג geny לדוגמה static loger אבל יש classסים שהם static classes וזה וזה לא יכול לעבוד בתוך genס במקרה כזה יש overload שפשוט מקבל tyפ אז אתם פשוט אומרים tyפ of static cloger זה לא יעבוד ב יש לכם קלאסים שהם סטטיים בקוד >> בודאי לאטיק [\[10:44\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=644s) ממש >> אוקיי אתם מה ההבדל בין קלאס שהוא סטייקס לקס שהוא לא סטטי >> קסמנציאצי אפשר להוסיף לו nonסטatic meods בגדול מבחינת הקפילר אוקיי אז הייתי אומר לכם פשוט תורידו את המילה statטיק זה לא כזה משנה לא חושב שנש יכול להיות exנשod לא יכולים להיות בקלאסט לא בטוח כן כן בלי בטוח נכון כן בסדר exנש מוד אתה לא צריך לעשות את זה גם אבל אם אתה באמת רוצה אז אתה יכול פשוט לכתוב [\[11:18\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=678s) ואז אין ד אפשר >> בטח שאפשר >> כן אבל אז אתה פשוט נותן type of static logoer במקום הגנרקט type ואז זה עובד בסדר עכשיו מה שקורה המתודה הזאת היא הולכת על כל הסטטיקס בקס ועושה להם פיק ואז אם מחר יש לך עוד שלוש שהוספת by defaultט הם יהיו fake וזה חשוב מבחינת maטity אז אבל אם הייתי רוצה רק להשתלט על אחת מהם הייתי יכול להגיד isolate when call [\[11:49\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=709s) אותו למדה שהיה לי גם קודם static loger right לא אכפת לי עם איזהסטרינקודה נגנור קוד ומאותו רגע המתודה הסטטית הזאת לא תעבוד דרך אגב באותה מידה זה גם יכול להיות extension אין שום בעיה בסדר אז אז גם עובדים ככה ההבדל בין הקריאה הזאת לקריאה שמ מעליה היא שהקריאה הזאת היא פחות מינable אז אם זה כל מה שאני צריך סתם שזה יהיה פייק הייתי כבר עושה פיק לכל הסטatטקic meods כי זה בדרך כלל מה שתרצו לעשות ואז שיש לו statטקוד אחד בדרך כלל לא אכפת לכם גם מאחרים אלים כן אתם בודקים אחד ואז אתם יכולים להגיד fake everything ואז when call על זה אתם יכולים להגיד call [\[12:32\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=752s) >> זה עושה over כאילו >> בדיוק זה תמיד לפי האחרון בסדר ואז בעצם זה עושה אינורס כן אה עשית משהו מיוחד בקומפילציה של סטטיקלוגיות כדי לאפשר את הפרופיילינג הזה או שזה יכול להיות כל דבר >> פרופיילינג זה חלק מהCLR זה לא קשור בכלל לקוד שאני כותב חות >> ככה DLL כבר קיים מקופה על הפילוה שלך ולעשות את כל הדבר הזה בעצם מה שהרבה אנשים עושים הם עושים פייק ל-SharePoint למרות שלא הם כתבו את זה אז הם עושים פייק לזה שכשאתה מריץ משהו ב-ASP.NET [\[13:02\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=782s) אז זה עושה פייק לפיג בפיג רוב המתוד שלו סטיר לhthp rec אפשר לעשות פייקים בעצם תקח כל dlיקרוסופט crm whatverבר תעשה לזה פייק אין שום בעיה כי התהליך הוא אותו תהליך כן >> כשאנחנו מוסיפים כאלה דברים כמו calls נגיד להפעיל משהו >> כן >> אנחנו יכולים לעשות את זה כמה פעמים או לבטל נגיד חוקים שהגדרנו כאלו >> כן אתה יכול לעשות אתה יכול להגיד שבפעם הראשונה תעשה אוריגנal ופעם שנייה שת תעשה את זה אז אתה יכול להגיד will throw exception ואז אחד הוא יעשה ומאותו רגע הוא יזרוק אפtion עד סוף הפוס >> נו אז זה תמיד דורס את הפעולה >> זה לא דורס ברגע שמת שניים עושה Q >> אה אוקיי >> כן אבל האחרון נשאר >> אז הוא קורא לו אוריגנל ואז אחר כך עושה [\[13:49\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=829s) >> כן במיוחד שאתה עושה ככה ואז אני יכול לראות בטest שזה יהיה הסדר של הפעולות עוד דברים עכשיו אם אני רוצה לבדוק שהפונקציה נקראה אני יכול להגיד was called with any ‏argumentס אוקיי אז תחשבו מבחינתי אני עושה פייק לדבר הזה ואז אני בודק שהוא ניכר >> גם כאן יש את הקולבק נכון >> יש את הקולבק תמיד זה לא משנה מתי הקולבק הוא קולבק אני יכול להגיד זה זה [\[14:22\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=862s) עוד דברים חשובים זה באמת קצה הקרחון זה רק הדבר הכי בסיסי שבדרך כלל נורא נורא קל להראות אתם אני הייתי שמח שאחרי זה אתם תנסו את זה על המחשב שלכם כי זה לא משנה כמה אני אראה לכם את זה שיש לי גרסה קצת יותר ישנה עדיף שתעשו את זה מגרסה האחרונה הנה אותו דבר עם static loger static we תעשה לי fake לstatic me של static we servic ler [\[14:54\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=894s) When static loger right will thr new ler exception ify was with any argum static בעצם אני לא חייב לגעת בכלל בפודקש קוד כדי שהדבר הזה יעבוד אני לא צריך לשנות שום דבר שאלות לגבי זה נכון תשימו לב אין לי פה מוק וסטאב נכון אין לי פה בכלל את המשהו שאני עושה ליפי אני הולך ישר לדפנenנס עצמו ואני בודק אותו אוקיי תך דברים יותר מעניינים אוקיי, [\[15:32\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=932s) עכשיו נלך לfuture objects. אם אני רוצה להשתלט על future object, אני יכול לעשות גם את זה. אני יכול לעשות fake instance של reloger ואז להגיד isolate swap next instance של reloger with fake loger. אוקיי? ואז בפעם הבאה שיהיה fake instance הוא לא באמת יחליף אותו. מה שהוא יעשה שיעשה interטרceפtion לכל הקריאות על הרeloger פשוט יעשה להם לפיק instance שלנו. ואז אני יכול לעשות verify was called על הפיק looger שלי שעדיין בעצם לא נוצר כביכול [\[16:02\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=962s) אבל הקריאה הזאת היא לא מספיק maable בגלל מה קורה אם יצרו 100נסים של הדבר הזה זה יעבוד רק לראשון יש instance לא allפס אין בעיה פקס swפ יופי אז זה באמת גרסה ישנה כי בגרסה החדשה יש all instanceses שמאפשרת בעצם לעשות את אותו דבר אבל היא עובדת גם על כל האינסטנסים הקיימים וגם על כל האינסטנסים הבאים 100,000 לא משנה גם אם יש לכםסינגלטון של loger נקסance אז הוא בעצם מוחלף באותו רגע בפיק אסנס שלכם [\[16:41\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1001s) אוקיי >> זה רטרוקטיבי אתה אומר >> רטרוקטיבית בדיוק זאת אומרת זה עושה אינטרספט לכל דבר מהטייפ הזהו על זה כ >> זה ייצר חדש אחד או ש >> הוא לא צריך הוא לא ייצר שום דבר הוא פשוט עושה אינטרספט כל פעם שיעורי קריאה לטייפ הזה תחשבו על זה כאנט נקי אבל מבחינת הצורת עבודה שלנו בPI זה נראה כביכול אנחנו יוצרים איסטנס אבל הסיבה היחידה שאנחנו יוצרים את האינסטס הזה זה כדי שנוכל לקנפג אותו לעשות עליו verify וכולי אבל האינס הזה הוא בסך הכל הרדירקט שלנו ועליו נוכל לבדוק את הדברים הוא מייצג לנו את כל האינסטנסים [\[17:14\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1034s) בסדר אם היו טestטים קודמים שקראו משהו שהיה עשה נירגד >> אם היו טסים קודמים אז חשוב בשגל זה לשים את האייסולטד הזה אחרת הטestטים יכולים להתערב אחד בשני וזה מנקה בין test לטestט את כל הטריות וכל הדברים כן >> זה עובד גם על קלאסים שורשים מריגר במקרה הזה כלומר איך זה מתנהג עם תורשעה >> אני זוכר שפעם זה לא עבד ואם אני לא יודע אם הוסיפו את הפיצ'ר הזה שזה גם אתה יכול להגיד כל הדברים שיורשים אבל אני לא באמת סופר אני צריך לבדוק את זה אוקיי [\[17:50\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1070s) אמ אז ככה אני יכול להגיד שכל ‏future instances recפג את הrger instance שימו לב זה לא משנה באמת אם יש לי או לא משנה מה והנס instance פשוט רוק אז אני יכול ככה לדמות המון דברים בלי לגעת בפרק מבחינתy c זה יכול לפתור המון בע >> אה שאלה שעלתה מהכיוון של שי שאני טוהל לגביה בסדר אה אנחנו בעצם רק עושים אינטרס למתודות כאן נכון >> מה זאת אומרת >> אנחנו לא מחליפים לאף אחד את האינסטנס האינסטנס נשאר >> זה זה מה שאמרתי האינסטנס לא באמת מוחלף מבחינת הדיבגר אתה תראה אבל האיסולטר יודע להראות לך בדבאגר שזה פיק אינסטנס ודרך אגב זהטר הוא היחיד שיודע שאם אתה מדבג איזשהיא קריאה של הפיק instance בדבאגר נגיד אתה משנה אותו או אתה עושה לפרטי ואמרת לו להחזיר פעם אחת שלוש אז הוא יודע הוא מספיק חכם להגיד [\[18:50\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1130s) אה ראו את זה בדבאגר אז אני לא אתייחס לזה זאת אומרת הוא לא משנה את ההתנהגות שלו בגלל שראית אותו בדבאגר אתה האינסטנס מבחינת הקוד הוא אתה לא רואה שום דבר >> השאלה היא לגביס >> השאלה היא לגבי לוקים אם אני אעשה קל על אינסטנס של טיפוס מסוים >> כן >> ואני מחליף אותו >> אה >> האם זה יכול איכשהו לפגוע לי בלוגיקה אותו ולכן חשוב אתה לא מחליף אותו זה בסך הכל אינטרספט על האנס מבחינת ה זה נראה כמו אז אינטרספט >> בכל מקבל אתה לא בד קסדים אז לא משנה לא אבל הוא שואל האם אתה יכול להריד [\[19:25\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1165s) Test עם typ שזה דרך אגב הרבה אנשים עושים הרבה אנשים עושים integraation tests אני גם הכרתי אנשים שלקחו השתמשו בטyוק סתם כדי לפתור איזה באג של אחד הפלאגינים ביזל סטודיו מה שיש פלאגין של איזה אחד מהmים שאני זוכר שמישהו אמר תשמעו הנה אני משתמש בטימוק הסתכלתי ברפלקטור ראיתי שיש שם בעיה בבאג אבל עד שהם יעשו אז אני אז זה מריץ פלאגין משלי שמריץ טקוטו ומשתלט על האינסטance הקיים של הפלאגין בVUDI [\[19:58\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1198s) ומשנה לו את ההתנהגות יש עוד אנשים שמשתמשים בזה כדי לעשות פייק לכל ה-SharePoint איפסטרקר כדי שהם יוכלו לעשות להריץ את ה-SharePoint איך קוראים לזה הטלט כאלה >> >> אבל בלי בלי להריץ SharePoint serverבר כן אז כדי להריץ ארט בסרבר לוקלי מה התחובה עם האם עושים פיקט פיקט אי אפשר לעשות כי זה בספורלי זה בכוונה מנוטר [\[20:36\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1236s) מהצל לראות מה יכול >> תנסה לעשות את זה עם מולז אני לא יודע אם אפשר נראה לי שגם שם אי אפשר עוד שאלות שורה הוא מחליף כרג נראה do state שהap כרגע לא מאפשר אבל אני מקבל קונטקסט לקונטקסט יש פרמטרים ואז אני יכול לבדוק את הערך של כל פרמטר לשמור את המידע ולעשות עם זה משהו אוד דברים חשובים אוקיי מבחינת הAPI יש עוד כמה דברים נחמדים [\[21:10\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1270s) Isolate non publicק הרבה פעמים בקוד לגסי מה לעשות יש דברים שהם ‏non puיק ואתה כן רוצה לבדוק אותם או לפחות רוצה לשנות את הבייר שלהם אוקיי אז אני יכול להגיד non public w public property אוקס ופה לתת strינגים עם השמות של הפונקציות אני גם יכול לתת שמות של non public static ואז אני נותן לי את הטyפ שעליו הסטטיק נמצא בסדר אז יש לי איזה priveי statטיק איפשהו ומשום מה אני לא יכול לעשות אותו פאבליק אני יכול עדיין לשר את הבי שלי אין שום בעיה פשוט ההבדל היחיד הוא שאין לי intellicence. [\[21:48\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1308s) בסדר? זה באמת היכולת של פרופיל. זה באמת לא משנה. מה אני מנסה לעשות פייק? אני יכול לעשות isolate fake static conסטור שלי מסוים. ואז אני יכול להגיד אם יש לי סטy קונסטרקטור שאוטומטית הולך וקורה קונפיגורציה אז אני יכול להשתמש בזה כדי לנטרל את הקונפיגורציה ולהריז את המערכת בזיכרון. אני השתמשתי ביכולת הזאת הרבה כתבתי framewורק שלם שנקרא [SilverUnit](https://osherove.com/videos/2009/8/25/unit-testing-in-silverlight-silverunit-and-ms-sliverlight-te.html "Unit Testing in Silverlight - SilverUnit and MS Sliverlight Test Framework (osherove.com)") והוא מאפשר לעשות [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") של [\[22:23\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1343s) קונטרולים שלסילברלי בליסברלי בלי brזר אז הוא בעצם מה שהוא עושה הוא עושה פיק לכל ה-Silverlight אפסטקuc מלמטה ועושה פייק של הכל של האבנטים של הקריאה לבראוזר של וכולי אבל אז במגום לעשות פייק ברמה הקרובה ביותר לפני השטח הוא עושה פייק ברמה הנמוכה ביותר זאת אומרת הוא הולך ואומר אה בסוף כולם קוראים לפונקציה הזאת הזאת. אוקיי אז נעשה פיק לפונקציה הזאת שהיא נמצאת שלוש חבות למטה באיזשהו ביס קלאס שאף אחד לא מכיר ואף אחד לא רואה ומה שמעניין היה זה שזה בכלל שזה עמד בפני ארבע גרסאות של סילבריט ולא הייתי צריך לשנות אפילו שורה של קוד רק בגרסה האחרונה של סילברליט היה צריך לשנות איזה כמה שורות של קוד כדי שהדבר הזה ימשיך לעבוד עכשיו איך עשיתי את זה יש exensibility mean לאolator [\[23:11\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1391s) בסator יש dll שנקראי אתם יכולים להירשם שם להוקים של שבעצם מה שעשינו זה חספנו את ההוקים של של הפרופיילר כביכול פרופיילר חספנו low level hs שמאפשרים לכם לבנות ty מייסטור משלכם זאת אומרת אתם מקבלים את השם של המתודה שעומדת להיקרה את הפרמטרים שלה ואז אתם יכולים לבנות פריימורק שלם לדוגמה אני אראה לכם איך זה נראה [\[23:47\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1427s) אוקיי אז בניתי פריורק שלם של openource שנקרא [CThru](https://osherove.com/blog/2009/2/25/adding-method-missing-support-to-vbnet-using-ctru-and-typemo.html "Adding Method-Missing support to VB.NET using CTru and Typemock Open-AOP (osherove.com)") שמשהו מאפשר יופי לא כלום מדהים הסקול עובד רק לכיוון אחד לא יודע איך זה קורה אולי יש פה איזה טייפמוק מותקן אני לא יודע אוקיי אמ אז לדוגמה אז הספרו הוא בנוי על גבי הtym hooksס והוא מאפשר API נורא נחמד אז אתה יכול לבנות דברים כמו fluent AOP אז אני יכול להחליט שאני בונה framewor שנראה ככה אני יוצר new AOP ואני אומר AOP skip method whenever [\[24:28\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1468s) Arguments type name contains under test ואז זה לא משנה בכלל מה או תלך לכל המתודות שיש להם יותר משני הארגומנטים ותגרום להם להחזיר אפtion אתם מבינים סוג הדבר דברים שאתה יכול לעשות עם הדברים האלה זה סוג הדברים שאתה יכול לבנות איתם פריימורקים בשביל טestטים זאת אומרת לקחת מייקרוסופט CRM דברים שאתה יורש מהם ולהגיד אני יכול רוצה עכשיו לבדוק משהו בלי האינפסטרקצר שלו בסדר זה סוג הדברים ש שבאים רק עם אחרי אחרי שמגיע הצורך אז בנינו אז יש פרימוק שלם שבנוי על tyפורק שנקרא וואי כבר שכחתי את השם שלו כל המטרה של הפריורק הזה זה לעשות עשות fake לasp.netwages אתפג יש לו API שאתה יכול לעשות פיק לובes [\[25:12\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1512s) יכולת לעשות את זה עם טקנוק אבל זה ייקח המון המון קוד אז הוא בעצם נותן לך API ממש ממש נחמד שבדפולט כבר פותר לך את כל הבעיות אתה רק אומר לו מה יקרה מתי ההתנהגות וגם מהר זה נורא נחמד שאלות >> מה זה הקונטeקסט שם בתוך דיןסד >> איפה נכון >> בקוד כן >> הקונטeקסט זה בעצם הנותן לי את הפרמטרים את השם של המתודה כל הדברים מהסד מה את עושה שם >> במקרה הזה? >> שורה אחת של הסמה לתוך טקסט לא מקרה זה אני סתם שומר את זה שופר [\[25:46\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1546s) >> זאת אומרת זה מה שאני בדרך כלל עושה במקום להשתמש ב was called with arguments mature בסדר כי אני מאוד לא אוהב את הapi הזה זה אני חושב אחת הטעיות הגדולות שלי שזה נתתי לapi הזה לקרות אבל זה דברים שלומדים רק מניסיון מאוד אהבנו אותו כשיצרנו אותו וכבר אז כבר לא זכרתי איך משתמשים בו עד כדי כך הוא מסובך למרות שהוא עושה דברים מדמים. עוד שאלות. טוב, אז מה שנעשה עד 5 :3 תתקינו טימוק [\[26:21\]](https://www.youtube.com/watch?v=vO-KpCDopU8&t=1581s) ותנסו לכתוב את הטestטים של הפuture object או של הסטיק. תבחרו לכם אבל תיקחו את הזיפייל המקורי לפני ששיניתם אותו ועשיתם בריפקטור ותראו אם אתם יכולים לכתוב את אותם טסטים בלי לגעת בפרודקש. בסדר? בהצלחה לצקר. ## Related - [Constrained and unconstrained frameworks](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-6#ch06lev1sec1) · The Art of Unit Testing, 2nd ed., ch. 6 Constrained versus unconstrained frameworks, explaining why profiler-based Isolator can fake statics and any class. - [Isolator Feature Focus: Duck Typing and Isolate.Swap](https://osherove.com/blog/2008/11/2/isolator-feature-focus-duck-typing-and-isolateswap.html) · osherove.com Covers Isolate.Swap, related to the future-instance faking the lesson demonstrates without touching production code. - [JustMock and Moles – A short overview for TDD alpha geeks](https://osherove.com/blog/2010/5/25/justmock-and-moles-a-short-overview-for-tdd-alpha-geeks.html) · osherove.com Overview of JustMock and Moles, the other profiler-based tools the lesson says need the same setup. - [Is Typemock too powerful? Will it kill design for testability?](https://osherove.com/blog/2008/1/17/is-typemock-too-powerful-will-it-kill-design-for-testability.html) · osherove.com Debates whether faking anything with Typemock hurts design for testability, a natural question after this demo. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 #### The Art of Unit Testing, 2nd ed. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 #### osherove.com - [Minimizing unit Test Fragility – 8 features in Typemock Isolator to help](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html) - [Introducing SilverUnit](https://osherove.com/blog/2009/2/25/introducing-silverunit.html) - [Adding Method-Missing support to VB.NET using CTru and Typemock Open-AOP](https://osherove.com/blog/2009/2/25/adding-method-missing-support-to-vbnet-using-ctru-and-typemo.html) - [Using TypeMock vs. Design for testability](https://osherove.com/blog/2006/9/27/using-typemock-vs-design-for-testability.html) - [FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition?](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html) - [Unit Testing in Silverlight - SilverUnit and MS Sliverlight Test Framework](https://osherove.com/videos/2009/8/25/unit-testing-in-silverlight-silverunit-and-ms-sliverlight-te.html) [Previous lesson Controlling Time](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/controlling-time/) [Next lesson Day 2 Summary](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/day-2-summary/) --- title: "Day 2 Summary" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/day-2-summary.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/day-2-summary/" tags: [] author: "Roy Osherove" description: "Lesson 15 of 22 in TDD in .NET in Hebrew (Day 2 - Legacy Code Tools), 2:23. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Day 2 Summary 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 2 - Legacy Code Tools Lesson 15 of 22 Duration: 2:23 [Watch on YouTube](https://www.youtube.com/watch?v=s6PktH7R5iY) Spoken in Hebrew ## In this lesson Roy Osherove previews the third day: the group will take an open-source project that has no tests and is mostly static and write tests for it both without and with [Isolator](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html "Minimizing unit Test Fragility – 8 features in Typemock Isolator to help (osherove.com)"), learning another [refactoring technique](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") on the way. They will also turn the practices discussed so far into a more formal set of things to look for, [review tests](https://osherove.com/videos/2011/2/6/how-to-do-test-reviews.html "How to do test reviews (osherove.com)") from open-source projects, and, if time allows, write tests for the participants' own code. ## Transcript 303 words [\[00:04\]](https://www.youtube.com/watch?v=s6PktH7R5iY&t=4s) מי הצליח להריץ כמה טestטים עםטו? כמה זה יותר מאפס? >> יותר מאחד. >> יותר מאפס. אוקיי, אל תצלם. א, אני ראיתי כמה אנשים שנדלק להם אני אצרוץ בעיניים שהם ראו את זה עובד בפעם הראשונה. אז אני שמח לראות את זה. מחר אנחנו ניכנס לקוד לגסי אמיתי. אנחנו ניקח פרויקט אקסורce שאין לו טestטים והוא ברובו סטטי גם ואנחנו ננסה לכתוב לו טestטים אנחנו נכתוב טestטים גם עם איסולטור וגם בליטור זאת אומרת גם אני אלמד אתכם עוד טכניקת ריפקטורים חדשה [\[00:37\]](https://www.youtube.com/watch?v=s6PktH7R5iY&t=37s) ואתם תלמדו לעשות טestטים בלי או לפחות להתקדם לאנשהו בלי איסוליטור ואז אנחנו ניקח את אותו פרויקט ונכתוב לו גם טestטים עם איסולטור וזה הפעם זה יהיה טestטים שידרשו הרבה יותר מהפרימוק בסדר בנוסף גם נעשה testw נסתכל על best practices וesting ניקח את כל מה שלמדנו נהפוך את זה לסוג של משהו קצת יותר רשמי דברים שצריך לחשוב עליהם כסוג של convenס ווגם נסתכל על קוד על testים מפרויקטים אחרים שהם open source ונחפש בהם בעיות כי אחד הדברים הכי חשובים כדי להמשיך את מה שאנחנו לומדים פה זה לדעת להסתכל על טestטים של אחרים ו ולעשות להם רו [\[01:20\]](https://www.youtube.com/watch?v=s6PktH7R5iY&t=80s) ולדעת מה לחפש אז אנחנו ניקח את כל הדברים שדיברנו עליהם עד עכשיו בצורה יחסית לא פורמלית פה ושם ונהפוך אותם לסדרה של סוג של מתודולוגיה מה לחפש ואיפה מתחילים שאלות לגבי מחר דברים שאתם אולי רוצים לעבור מחר גם שלא אמרתי אם נישאר זמן אם נצליח אז לקראת סוף היום ננסה לכתוב כמה טestטים לקוד הקיים שלכם ביחד ואם לא אז ביום ראשון ושני לפחות נתחיל בזה אני אצטרף אליכם ונעשה את זה בזוגות [\[01:57\]](https://www.youtube.com/watch?v=s6PktH7R5iY&t=117s) נכתוב קוד אני מתקבלת אוקיי >> כולם לא אוהבים כאן לכתוב קוד בדרך כלל >> טוב אז אם אין שאלות נתראה מחר ב7 ו3 נכון בערב תע להתראות ומחר תעשו את הקטע בבוקר תעשו לי טובה בסדר זה לא בשבילכם זה בשבילנו אז כי במקום הלך ## Related - [Test Review Guidelines](https://www.artofunittesting.com/unit-testing-review-guidelines) · artofunittesting.com A checklist for reviewing tests under readability, maintainability and trust, like the formal list previewed for day three. - [Video: how to do test reviews](https://osherove.com/blog/2011/2/6/video-how-to-do-test-reviews.html) · osherove.com Roy reviews tests in open-source projects and explains what he looks for, the exercise planned for day three. ### Also linked in this lesson #### The Art of Unit Testing, 2nd ed. - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 #### osherove.com - [Minimizing unit Test Fragility – 8 features in Typemock Isolator to help](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html) - [How to do test reviews](https://osherove.com/videos/2011/2/6/how-to-do-test-reviews.html) [Previous lesson Working with Typemock Isolator](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/working-with-typemock-isolator/) [Next lesson Unit Testing Best Practices](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/unit-testing-best-practices/) --- title: "Unit Testing Best Practices" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/unit-testing-best-practices.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/unit-testing-best-practices/" tags: [] author: "Roy Osherove" description: "Lesson 16 of 22 in TDD in .NET in Hebrew (Day 3 - Unit Testing Practices), 35:00. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Unit Testing Best Practices 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 3 - Unit Testing Practices Lesson 16 of 22 Duration: 35:00 [Watch on YouTube](https://www.youtube.com/watch?v=L7m3myFfWMk) Spoken in Hebrew ## In this lesson Roy Osherove groups his rules into tests that are readable, [trustworthy](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7 "Trustworthy tests (The Art of Unit Testing, 3rd ed., ch. 7)") and [maintainable](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)"), and tells how a [bug in a test helper](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11 "How can we know we don’t have bugs in our tests? (The Art of Unit Testing, 3rd ed., ch. 11)") cost him and a [pairing partner](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html "How Do You Explain Pair Programming? (osherove.com)") 90 minutes on a Go engine built with [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)"). For [trust](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134 "How to know you trust a test (The Art of Unit Testing, 3rd ed., ch. 7)") he separates [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") from [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)") that need configuration, so a failing unit test is never "fine", and recommends [code reviews that start from the tests](https://osherove.com/blog/2007/3/13/test-reviews-vs-code-reviews-some-helpful-tips.html "Test Reviews Vs. Code Reviews - Some Helpful Tips (osherove.com)"). He argues that [code coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)") means little without reviews, then reviews a test from [Microsoft's Unity](https://osherove.com/blog/2009/3/23/test-review-3-unity.html "Test Review #3 – Unity (osherove.com)") source that has no expected behavior in its name, a loop and [several asserts](https://osherove.com/blog/2005/4/14/try-to-avoid-multiple-asserts-in-a-single-unit-test.html "Try to avoid multiple asserts in a single unit test (osherove.com)"), and prefers [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)") to [removing duplication](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_161 "Keep tests DRY (The Art of Unit Testing, 3rd ed., ch. 8)"). ## Transcript 5,263 words [\[00:02\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=2s) אוקיי אז ככה טוב לא מי את המצלמה עוד וטרפל מציתך דרך אגב ש מצלמה במקום אחד כל הקורס >> >> היא לא באותו מקום כל הקורס >> איפה היית צת פעם שמה שם >> כל היום היום אנחנו הולכים לעשות לחלק את היום הזה לשני חלקים בחלק הראשון אנחנו הולכנו לדבר על practices, דברים שצריך לעשות או כדאי לעשות בזמן שכותבים [\[00:36\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=36s) Testים. אנחנו נעשה קצת פורמליזציה לחלק מהחוקים שתמיד אני מבקש ממכם לשמור עליהם. אז אנחנו נדבר עליהם ב תחתוב של שלושת הרעיונות המרכזיים במה עושה עושה טestטים טובים יותר. טובים יותר זאת אומרת מחזיקים לאורך זמן קריאים יותר טestטים שאנחנו סומכים עליהם. אחרי זה קצת נסתכל על קוד של פרויקט קיים וננסה לכתוב לו testingים [\[01:06\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=66s) אבל לפני זה גם נסתכל על קודים של כמה פרויקטים open source וננסה להסתכל על הטestטים שלהם ולראות אם אנחנו מוצאים שם בעיות או דברים שהיינו רוצים לשפר ובעצם לקראת סוף היום אנחנו נכתוב טestטים לקוד קיים כולל קוד שיש לו testingים אבל לא [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1 "Defining unit testing, step by step (The Art of Unit Testing, 2nd ed., ch. 1)") זאת אומרת קוד שיש לו ‏test ו שיאפשר לנו לעשות רפאקטורing ולודא שלא שברנו שום דבר או לפחות לראות איך זה מרגיש כשיש סיד של inration test שמאפשר לנו לעשות כרצונינו בקוד וממש להתקדם עם testing [\[01:44\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=104s) אז בעצם שלושת החלקים של testים שמבחינתי נחשבים טובים זה readable [trustworthy](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec1 "Writing trustworthy tests (The Art of Unit Testing, 2nd ed., ch. 8)") maaintainable או RTF או RTM אבל היה כמובן תמיד איזה חכמולוג שאמר תעשה את זה RTFM כי זה גם צריך להיות מהיר אז RTFM test זה אחד הדברים החשובים שצריך שיהיה אז >> RTFM במושג המקורי או במושג הזה במושג המקורי מכן >> readable trustable fastי [\[02:16\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=136s) >> אוקיי אם אנחנו רוצים שהנושא של unit testing יצליח בחברה אנחנו צריכים לדעת ולהכיר אה איך איך לקרוא טestט ומה לחפש בו כדי למצוא בעיות, כדי לשפר אותו. וזה הנושא של testwס. עכשיו אני יודע שהיום אתם עושים קודw באיזשהי צורה, נכון? >> מישהו פה עושה קודw? גם אוקיי, אז מה שאנחנו נעשה זה שאנחנו גם בחמישהים שאני אהיה פה וגם אחרי זה, מה שאני מקווה שתמשיכו לעשות זה שגם כל הטestטים שנכתבים יעברו קודיו. [\[02:50\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=170s) בעצם הם יעברו קוד רוw ראשונים והרעיון הוא להתחילקוד רוwז מה 100טestטים כי בדרך כלל אם מתחילים קודיו מהטestטים לפעמים יותר מהר למצוא בעיות או בעיות בהבנה של ה של הבן אדם שכתב את הקוד בגלל שהשם של הטestט לפעמים אומר שהבנת את הדרישה בצורה לא נכונה ולפעמים זה גם פשוט קל יותר לעשות דרילדאון כדי להבין איך כל הפיצ'ר שמישהו כתב עובד אז תחשבו על זה שטest טestטים הם בסך הכל דוגמאות לאיך פיצרים עובדים במערכת אם אנחנו חושבים על זה במושג של אז במקום סתם להגיד אוקיי איזה קלאסים שתנו זה יותר תראה לי איפה הנטריפ point של הפיצ'ר הזה ובוא נתחיל לראות איך משתמשים בו גם מבחינתity גם מבחינת ההבנה שלך של הפיצר גם אפשר לעשות drלדאון לכל פונקציה שאנחנו קוראים לה [\[03:37\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=217s) אז מבחינתי אם מוסיפים testwס הקודw יכול להיות הרבה יותר מהיר מבחינת מציאת בעיות וותיקון שלהם אוקיי דברים שאני אני מחפש בestw הם קשורים לשלושת החלקים האלה mainity וust למה חשוב לי שהטestטים יהיו קריאים זה נשמע פשוט אבל למה זה בכלל חשוב זה לא שאין טestטים בלתי קריים בעולם איך זה משפיע קריאים יכול להיות בהם בעיות ואם יש בהם בעיות אז זה הכי גרוע >> אם יש בעיות בטסטים זה הכי גרוע למה [\[04:15\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=255s) טסטח ס אני אתן לכם דוגמה אמ אני עכשיו עושה סדרה של אה וידאוים של [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6 "Test-driven development (The Art of Unit Testing, 2nd ed., ch. 1)") שאני עושה פרingנ עם מישהו בכלל בסאטל במקרה הוא עובד גם במייקרוסופט הוא אחד מהחבר'ה שעושים טestטים ל לוינדוס אחד מהצטסרים של ווינדוס פונ אז אנחנו עושים פרing ברמוט ואנחנו עושים משחק שנקרא מישהו מכיר אתג משחק סיני עתיק אז אנחנו עושים מנוע שלג go בTD [\[04:46\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=286s) זה משחק שהוא לא כזה מסובך הוא גם לא כזה פשוט, נורא נורא מעניין. אז סילמנו כבר שישה, שבעה וידאוים כאלה, משהו כמו תשע שעות ביחד סך הכל. ובסך הכל תחשבו שתשע שעות זה יום וחצי של עבודה בתור זוג. וב ב באיזודה האחרונה שהיא בערך שעה וחצי זה 90 דקות של תסכול מצד מצידי ומצידו. אוקיי? זאת אומרת מה מה את רוב ה-90 הדקות פילינו בלהבין למה הטestטים נכשלים. [\[05:17\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=317s) ואיך לגרום להם לעבור. למרות שאנחנו כתבנו ביחד את הטestטים. אז הדברים שעזרו לנו להבין מה הבעיה היו השמות של הטestטים. השמות של הטestטים הצילו אותנו כדי להגיד וואלה יש לי חמישה טestטים שנכשלים אבל וואלה אני רואה רק לפי השמות שהטest הזה הוא הרבה יותר פשוט מכל השער. אז הבעיה היא כנראה במקום אחר לגמרי ממה שאנחנו חושבים. רק הדבר הזה בעצמו יכול להציל אתכם. אני אדפיל את זה כדי להבין למה משהו קורה. אם אתם לא יכולים להבין למה הטest נכשל אז בגלל הרדילי אז אתם לא יכולים גם לתקן אותו המטנabity שלו גם נתקף [\[05:54\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=354s) אז ניסינו לעשות פיצר ואז הטסטים התחילו להכשל וגילינו דרך אגב שהבעיה היא בטestטים יש לנו היה לנו באג בטestטים באיך שאנחנו ממלאים את הלוח של הג עכשיו הבאג הזה לא קלטנו אותו ברגע שכתבנו את הקוד הזה את הבאג הזה מצאנו חמש שעות אחרי שכתבנו שני סשנים אחרי מבחינתנו להבין שהיה לנו באג בטestטים לקח לנו שעה וחצי ברגע שגילינו אותו לקח דקה לתקן אותו אוקיי אז מבחינת הטestטים יש כל מיני דברים שאנחנו עשינו בצורה לא נכונה שהיינו יכולים לעשות בצורה הרבה יותר טובה ומה שאני רוצה להגיד זה שזה לא משנה כמה ניסיון יש לכם אתם עדיין יכולים לעשות מה שנקרא roוק י מסקס כי אני זה שכתב את הטestט הזה ואת ואני זה שאמר וואלה אני לא צריך לבדוק את הלוגיקה הזאת בטestט אני תמיד אומר לכם וואלה אל תשימו לוגיקה בטסטינג זה סוג הדברים שלוגיקה יכולה לעשות לקחת זמן של שני אנשים 90 דקות כדי להבין למה משהו קרה ואם זה היה בן אדם אחד שעובד על זה [\[06:54\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=414s) 90 דקות הוא לא היה מוצא את זה שני אנשים היינו צריכים כדי לבדוק את זה כי רק הדבאגינ של הדבר הזה היה שעה וחצי וגילינו שני באגים באותה פונקציה שהיא helperפנקש בטestטים שלנו אוקיי אז זה יכול לקרות לכל אחד ולכן צריך מאוד מאוד להיזהר אז הנושא של trust זה אחד הדברים שאכל אותנו אנחס שמחנו על הטestטים שלנו ואז יום אחד גילינו שהטestטים שיקרו לנו הם לא גילו לנו שיש להם ב רק שניסו להשתמש בהם בסדר נוצת יותר מסובך פתאום גילינו שכל שחלק מהטestטים שכתבנו עד אותו רגע נתנו לנו תוסאה שהיא יכולה להיות שקרית [\[07:31\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=451s) אז היינו צריכים ללכת לכל הטסטים הקודמים ולבדוק שהם גם נכשלים כשהם צריכים להקשר אחרי שקילינו את זה למזלנו היה רק חמישה תרתיל אז בלי רדבילטity לא היינו בכלל יכולים לגלות את זה זה היה לוקח הרבה יותר מ-90 דקות. המיטבabity זה הרעיון שהטestטים מחזיקים הרבה זמן. כמה זמן הטestטים שאני כותב יחד עם הבן אדם הזה יחזיקו? הכוונה היא 5-10 שנים בקלות. אוקיי? ויש כל מיני דרכים כדי לוודא שהם יחזיקו מעמד. זאת אומרת שלא באיזשהו שלב ועוד שנה מישהו יגיד [\[08:02\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=482s) לוקח לי יותר מדי זמן לשנות כל פעם את הטסט כל פעם שאני אשן את הבורד שניות. Screw this אני לא רוצה לעשות את זה יותר. ואז מישהו מוחק את הטסט עושה לו איגנוור. הכי גרוע שעושים אגנור. מישהו עושה אגנור לטסט אף אחד לא יזיז את האגנור הזה יותר בחיים מהטest הזה למשך חמש שנים יהיה אגנור על הטest הזה מישהו ישאל למה יש אגנור מישהו אומר עזוב לא יודע אין לי מושג ואז האגנור הזה נהיה כמו כל חתיכת [קוד לגאסי](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") וזה שם אל תיגע תן תפגע וזהו אז הנושא של טestטים שמחזיקים מעמד קשור מאוד לרדבity כי אם אתה לא מבין למה הטest עושה מה שהוא עושה אתה יכול לעשות לו mainנס [\[08:38\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=518s) ואם לא יכול לעשות פה maנס אתה לא יכול לסמוך על אותו הם כולם מחוברים אז בואו דווקא נדבר על trust קודם כל trust זה אחד הדברים הכי חשובים שיש לנו בטestטים אם אנחנו לא סומכים על הטestטים אז כמעט הכל לא היה שווה לעשות את זה make it easy to run הקונספט פה אומר אם אני מסתכל עכשיו על פרויקט אחד הדברים שאני מסתכל עליהם זה בסutושtion לראות כמה כמה test projטס יש לי [\[09:08\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=548s) אם אני רואה שיש לי רק testקט אחד זה יכול להגיד כמה דברים יש לכם רעיונות מה זה יכול להגיד שפט אחד מתוך סלוש פרויקט אחד מתחסן >> רק פרויקט אחד מתוך הסולושן הוא פרויקט של טestטים זה מה שאני אומר מה זה אומר לגבי הסולשן >> שיכול להיות שהוא מרכז הרבה פרויקטים >> שיכול להיות שהוא מרכז הרבה פרויקטים יכול להיות שהוא רק לפרויקט אחד >> יכול להיות שכל הטestטים של כל הפרויקטים הם בפרויקט הזה זה [\[09:42\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=582s) אז מה זה בטוח אומר >> בטוח שכל הטסטים תמיד אותו אז תריץ את כל הטestטים שאם תריץ אותו תריץ את כל הטestטים שיש לך נכון אבל זה גם יכול להגיד כמה דברים אחרים זה יכול להגיד א' שיש לי אינטגרש test וניט test מחוברים באותו באותו פרויקט יכול להגיד או שאין לי מספיק testים אבל אם אני לא יודע זה אומר שאין לי מספיק readדity שלהבין למה משהו אה הטestטים של מה קשורים למה אם אני לא יכול להבין שיש יש את לפרויקט הזה יש טestי אז הרבה יותר קשה לי אחרי זה לעוב ולתחזיק את זה ולחפש את הטestטים [\[10:17\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=617s) אבל בואו נתחיל דווקא בדבר המרכזי אני רואה שיש רק פרויקט אחד מה שקופץ לי לראש זה שאנגרש test ו test הם מניingס במערכת הזאת זאת אומרת יכול להיות שחלק מהפקט מהטestטים האלה הםation חלק מהtestים הם unit מי זוכר מה ההבדל בין test >> זמן ריצה זמן ריצה יכול להיות ההבדל אבל זה לא חייב להיות חייבים לראות הרבה מאוד תנאים שניסים לעמוד בהרבה תנאים כמו היותים ברורים קצבים [\[10:47\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=647s) יש להם הרבה קונסטרנטים >> אבל בגדול מה ההבדל יש איזשהו הבדל מטה ביניהם זה כולל כמה >> עכשיו אני מרגיש פה באנטגרש test מה >> זה כולל כמה unityים >> כמה יוטים testל כמה testבדוק כמה דברים אבל יש משהו יותר חשובדביסים מה זה אומרפטי פטי אוקיי ומה זה אומר >> זה אומר ש >> מה metס פה האם יש לי שליטה בכל הדברים שאני בודק [\[11:19\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=679s) >> אוקיי זה ההבדל בינגרש test מבחינתי הם שניהם בדרך כלל ירוצו בזיכרון אני יכול לעשות test שהם מאוד מהירים אבל אם אני עושה integraation test עם random number generator והוא הכל בזיכרון זה עדיין מבחינתי [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec3 "Integration tests (The Art of Unit Testing, 2nd ed., ch. 1)") כי אין לי שליטה על המספר שיצא אוקיי גם אם עושה testing frדים גם אם הוא רק בזיכרון עדיין test כי אין לי שיטה על פרדים נפרדים זאת אומרת אני צריך להרוג אותם בנפרד אין לי שליטה על הדברים מהמערכת הנה הדבר הכי מוזר שקרה לי זוכרים עכשיו דיברתי לכם על משהו שהסשן של היה 90 דקות של תסכול אז היו שני באגים בבאג של הגו הבאג הראשון [\[11:56\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=716s) היה שאני עשיתיגט לדס לכל הטestטים והיו משהו כמו 20 טestטים סוף ואצלו כל הטestטים עברו ואצלי שני טestטים נכשלו אוקיי, הקוד היה אותו קוד, אצלי שני טסטים נכשלו ואצלו שני טestטים עברו. אז אחרי 10 דקות של דבאגנ אני מנסה להבין ואנחנו מבינים שאנחנו עושים ספליט לכמה סטרינגים ואצלי הספליטים מכילים newני line ואצלו הספיטים מכילים new line בסג [\[12:27\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=747s) ולכן אצלי הספליטים לא עובדים ואצלו הספליטים כן עובדים. אוקיי עכשיו לא היה פה שום דבר שקשור לקאלצ'ר. אמרתי אוקיי וואלה אולי אצלך משהו קשור לקלצ'ר במחשב ואז איכשהו ניולינס נראים אצלך אחרת אבל אז שתבינו לא בכלל לא חשבתי על זה שיכול להיות פה איזשהו אישי בסוף התברר ששנינו משתמשים בגיט ואצלנו הגיט מקונפג לעשות גט אין שהוא משנה את את הCRLF את את הקומנדל line ואת הרן כדי שבעצם הסטרינגים יהיו שונים בפיילים [\[12:59\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=779s) זה סוג של דוגמה למשהו שאתה כמעט ולא יכול לשים לב אליו אז פתאום אמרתי וואלה אולי בעצם כתבנו integrגרש test ולא שמנו לב עד עכשיו אולי משהו קשור לקצר אבל זה היה קשור בכלל לשימוש שלנו לקונפיגורציה של גיט אוקיי אז אפילו דבר כזה פשוט פתאום יכול לגרום לכם לתוצאות מוזרות עכשיו למה אני אומר את זה אני אומר שיש הבדל ביןגרש לוit test ואני אומר וואלה פה unit test ונingration test מעורבבים עכשיו לי יש בעיה עם זה שמערבבים unit test ואינטגרation test באותו פרויקט [\[13:31\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=811s) למה מה הבעיה? שת אתה מוריד את כולם ביחד בעצ >> מה >> אתה מוריד את כולם ביחד >> נו אז אני מוריד את כולם ביחד ו >> דבר ראשון זה פחות זה פחות מהיר >> יש לי זמן בוא נניח שיש לי זמן מה הבעיה testרך כנראה איזשהיא סביבה מוכנה מסוימת שאתה רוץ עליה לדע בדיוק מה היא test לעבוד אותו דבר הכל אז שם מתחילה מה שם מתחילה הבעיה שינטגרש בדרך כלל דורשים קונפיגורציה וטest אמורים לא לדרוש שום קונפיגור רציה זאת אומרת [\[14:07\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=847s) ב בbest cas סנר שלי אני אמור לעשות גטלי ואנריץ את כל הטestטים וכל היוטestטים אמורים לעבור ב-100% זאת אומרת אף אחד לא עושה צקור בלי שכל הוIT testים עוברים אבל test יש סיכוי שהם לא יעברו בגלל שיש לי קונפיגורציה שונה על המכונה כל מיני דברים אחרים הדatביס לא מותכן יש לי אקנ לא מותקן ואז אם אם הם ביחד באותו פרויקט יכולה להיות לי בעיה שה בעיה מאוד אנושית [\[14:37\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=877s) אני מריץ יש לי 100 טestטים שלושה נכשלים אני מסתכל אני שואל מישהו בצוות יש לך מושג למה הטסטים נכשלים ואז המישהו הזה בצוות יכול להגיד לי את הדבר הכי גרוע שצריך שאפשר להגיד למישהו שהריסטי ונכשלו זה בסדר אם אומרים זה בסדר אז אנחנו בעצם מפסיקים להאמין לטestטים אנחנו לא סומכים עליהם יותר על התוצאות האלה זה בסדר חסר לך דטבס זה בסדר אולי פשוט חסר לך קונפיגורציה ואז במקום להבין במקום בום לדאוג מהטestטים אני פשוט יוצא מקודת הנחה שהטעות היא לא אצלנו אלא הטעות היא בקונפיגורציה של המערכת ואז אני ממשיך הלאה הרבה פעמים אין לנו את הזמן ללכת ולקלטק את המערכת לכל האנטגרש test [\[15:16\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=916s) או פתאום טסט אחד נכשל ולפעמים לא נכשל ולא נכשל ואז מישהו אומר לא זה בסדר זה אמור להיקשל כל פעם שלישית עכשיו אם הייתי מפריד את זה התוצאה הייתה יכול להיות אחרת לגמרי אם אני מפריד את זה לנד unit test ונדגרation בחלק המינימלי אני יכול להניח שאני עושה gets verion לכל הפרויקטים עושה קליק ימני על הפרויקט של הניטestים והם כולם אמורים לעבור ואם אפילו אחד מהם לא עובר אני צריך להרגיש מודעג [\[15:48\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=948s) אני צריך להרגיש מודעג צריך להיות לי איזשהו saיגreין זone ביניט testing שהם כולם אמורים להיות ירוקים ואם אחד מהם לא ירוק אני צריך להרגיש דאגה ואני רוצה לעשות משהו לגבי זהרation test אני מכתחילה יוצא מכלת הנחה שצריך קונפיגורציה וצריך צריך כל מיני דברים אחרים ואז אני באמת פחות מאמין לתוצאות שלהם אבל מכיוון שיש לי פרויקט נפרד שהוא מובטח לי שהוא אמור לעבור כי הוא כולו אמור להיות unitest אז כמבחינת הביטחון שזה נותן לי זה ביטחון הרבה יותר גבוה להגיד וואלה בטestטים האלה שום דבר לא נכשל ואם משהו נכשל אז משהו לא היה בסדר אבל מכיוון שהכל עובר אז הכל בסדר מבחינת היוניטסטים האלה הכל בסדר זה נותן יותר ביטחון ויותר אמ ואני יותר בוטח בטסטים שלי אז השלב הראשון זה להפריד בין unitgגרation test כדי שאני אוכל לבטוח בתוצאות. [\[16:37\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=997s) אם יש לי תוצאות שבהם הדברים מעורבבים אז אני לא יודע אם מה שנכשל זה unit אונגרation test. ואז אני צריך להיכנס ולבדוק ולאף אחד אין זמן להיכנס ולבדוק את הדברים האלה ואז מניחים שאולי הבעיה היא בכלל בקונפיגורציה במקום בטest עצמו או ש או שלוקחים את הזמן ומגלים ואז מגלים שזה האינטגרש test והבקונפיגורציה ואז בטestט הבא שנכשל כבר לא עושים את זה יותר אז זה נותן לנו את הרישיון להתעלם מהתוצאות של הטestטים כשאנחנו מערבבים בין שני הסוגים האלה זה אחד הדברים החשובים שכדי לסמוך על הטestטים צריך להפריד ביניהם כדי שיהיה לי פרויקט אחד שעליו אני באמת יכול לסמוך בפרויקט אחר שעליו יהיו הוראות איך לקנפק וכל הדברים האלה ואני יודע שהפרויקט הזה לא בהכרח יעבור ב-100% [\[17:26\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1046s) אז דבר ראשון שאני עושה אני מסתכל על על המבנה של הסolution ואני מחפש אם יש בכלל פרויקט של test אם אין פרקט של integration tests אני מחפש subfoldרים של unit ונטגרation לפחות בקטע הזה לפעמים אנשים שמים קטגוריות של slow וfast זה התחלה אבל זה לא תמיד קשור למהירות ות ואם אני באמת רואה שאין את ההפרדה אז דבר ראשון שאני עושה זה כשאני עושה ריwטestטים החדשים שמישהו כתב אני מוודא שהטestטים שאני עכשיו עוד בודק הם נמצאים במיקום הנכון אני יוצר פרויקט שלי אם טestטים אין ואני שם אותם בפרויט שלי זאת אומרת מאותו רגע יש ברגע שאני עובר שם אז מאותו רגע לפחות כבר המצב יותר טוב ממה שהוא היה ל לבוב מרטין יש משפט שאומר חוק הצופים תמיד תשאיר מקום נקי יותר ממה שקיבלת אותו וזה נכון גם לגבי קוד אם אני נכנס לקוד אני תמיד משאיר אותו במצב יותר טוב ממה שקיבלתי אותו זה לא חייב להיות עכשיו ללכת לכל הטestטים ולשנות אותם במקרה שלכם זה דווקא כן יכול להיות אם יש לכם שמונה טestטים אז זה בסדר [\[18:26\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1106s) תחו את השלוש דקות האלה כל אחד לוקח טestט מזוגות ומשנים את המקום שלו למקום הנכון שאלות לגבי זה אוקיי קודק [coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)") אקד coverage זה משהו שבדרך כלל אני לא משתמש בכלים יותר מדי כדי לבדוק אותו. אני משתמש הרבה יותר בבדיקות ידניות כי אני יוצא מט הנחה שכל קוד שנכתב נבדק בקוד רב. [\[18:57\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1137s) אבל נשאל את השאלה כמה cod coverage זה coverage טוב? כמה קודג' צריך? 100% >> 100% אוקיי מישהו בדק את הקודק שיש לו דרך אגב על הסטרינקulator שהוא ניסה אולי יחס תעשו את זה תבדקו כמה קוד קורג יש לכם אם יש לי 90% קוד קורג בפרויקט אתה יודע מה אם יש לי 99% קוד קורג בפואט [\[19:28\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1168s) אוקיי יש לכם פה לוח והוא אומר 99% קוד זה טוב או לא טוב אפשר לדעת אי אפשר לדעת למה אי אפשר לדעת זה תלוי במה את הקוד הכי קריטי >> ה1% אוקיי >> לא אם הטestטים עושים את המטרה שלהם >> מה המטרה של הטestטים לא לעשות ק >> זה לא עניין רק של קוד זה עניין של תרחישים אם הם עונים על התרחישים שהכל מטפל בהם הם טסטים טובים יכול להיות שעל כיסיתי פונקציה מסוימת אבל לא כיסיתי אותה בכל מבחינת הדברים וגם גם יכול להיות קוד שהואגנט אוטומטיק שאין לי בכלל מה לעשות [\[20:06\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1206s) >> אוקיי >> אז זה טוב או לא טוב מספר >> זה לא אומר שום דבר >> זה לא זה לא המטרה >> זה לא המטרה אבל אני חשוב שתבינו שבהרבה ריבונים קודק coverage הוא כן מטרה קוד קורג ה הוא לא יכול להיות מטרה בפני עצמה בגלל שהוא לא אומר שום דבר על קולטיק הוא רק אומר coverage אם אני אומר לכם עכשיו תשיגו 100% קודo coverage תוך שבוע יכול להיות פה קודק coverage של 100% זה לא אומר שאתם בודקים משהו אני מכיר והרבה חברות שיש הרבה מתחים שעשו בדיוק את מה שאמרו להם אז הם הגיעו לקוד קבר של 100% אבל לא היה להם שום אסרטים אפשר לעשות את זה אין שום בעיה הגיעו למטרה שאמרו להם נכון גם ככה אין זמן אז יאללה טוב אמרו לנו להשיג קוד קורג שחייבים לעשות את זה זה עובר קודם בקוד קורג מריצים נגיע ל-100% אין שום בעיה [\[20:53\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1253s) אם יש לי 20% קוד קורג מה זה אומר זה אומר משהו >> זה לא הבדל זה לא שמ שזה בדלת מה >> לא נשמר שזה המדד >> לא נשמע שזה המדד אבל זה אומר משהוכ >> זה אומר משהו >> מה זה אומר זה אומר שיש לך עדיין קוד שאתה לא ניסית לעשות הגובות >> זה אומר שיש לך מה >> זה אומר שיש לך קוד בהנחה ש80% שנשאר הוא לא כולו קוד שאתה לא מעוניין גם לבדוק קוד שאתה לא יודע >> זה אומר בטוח זה בטוח אומר משהו וזה אומר שחסר לך טestטים >> בדרך כלל זה אומר משהו מעט מאוד חברות 20% מהקוד שלהם זה כל הקוד שלהם אלא אם כן זה חברות שמייצרות ID שמג'נרטים קודשהו [\[21:30\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1290s) אבל גם קוד מג'נר ד אפשר לכתוב לו טestי מגנרטים גם לטסט זה גם לא לא בלתי אפשרי אבל 20% קודק coverage אם 20% קוד אומר שחסר לכם קוד אבל 99% או 100% לא אומר שום דבר מה עושים עם המידע הזה איך אפשר איך אפשר ש100% או 99% קורג יגיד משהו זה לא כתוב פה יש לכם רעיון דאוג לקליט שלו >> איך דואגים לקולטי [\[22:05\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1325s) ‏Rw של הwטestטים אני מסכים איתך לחלוטין בליקוד revws cod cage לא שווה שום דבר קוד קורג גבוה הדרך היחידה שבה אני יכול לסמוך על cod cover cverage זה אם הקודק cover cverage הזה עבר גם testw אם אני יודע שהטestטים טובים והקוד קoverage גבוה אז אני יכול להגיד אנחנו במצב קל אוקיי זאת אומרת שאם אתם לא עושים testwusew אם אתם לא עוברים אחד לשני על הקוד כולל הטestטים זה לא משנה כמה קודק יהיה לך לכם יכול מאוד להיות שאתם משדרים לעצמכם. הדרך היחידה לדעת את זה זה ממש לשבת בין אדם מבן אדם ולעשות אינטראקציה אנושית ביניכם [\[22:40\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1360s) ולדבר עם אנשים וללמוד אחד מהשני ולהסתכל על הקוד. זה לא רק לשלוח קומנטים ולהגיד שכחת אסרט מהבית. זה לשבת אחד ליד השני ולהגיד וממש לדבר אחד עם השני. לדבר על התהליך חשיבה בכל רם להגיד אה מעניין אותי למה זה כתבת ככה. למה איך למה אתה בודק את זה ככה? מה אתה מנסה לבדוק פה? ממש לעשות דיון על הקוד הזה. זה גם דרך מדהימה ללמד ולהעביר ידע בחברה, אבל גם חשוב מאוד זה מוודא שאתם בודקים באמת דברים, אתם בודקים את הדברים הנכונים. [\[23:15\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1395s) >> אכן, אבל כן, כאילו בגלל זה אני חייב לדעת שאני לא מסכים איתך. אני חושב שבמקרה הזה מידה והבדיקות הם כן טובות. הקוד קורג כן מספק לך מדד מרגיע. כלומר, אם אתה בבדיקות הם טובות, אבל זה זה התנאי, אבל איך תדע שהבדיקות טובות? >> זה סבבה. ולכן אבל שוב אתה אומר שזה לא מוכיח ש שהבדיקות הן טובות אבל אם הבדיקות הם טובות זהח שהבדיקות זה יוכיח שאת במצב טוב אם יש גם testרwס וקודק coverage גבוה >> סבבה >> בסדר >> עכשיו בדרך כלל אם אנחנו עובדים בTD אני כמעט אף פעם לא בודק coverage זה אני אישית אבל אין לי שום בעיה שאתם תבדק coverage בגלל שבדרך כלל אני רגיל לעבוד בחברות יותר קטנות 10 12 יש פה כמה כמה ככה יש 18 [\[23:55\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1435s) זה כבר חברה יחסית יותר גדולה ממה שאני ממה שאני רגיל לעבוד בה אבל קודק coverage י יכול להיות מדד נחמד עם >> אבל מה כשאני בודק קוד של מישהו אחד הדברים שאני עושה זה אני יושב עם הבן אדם במקום סתם לבדוק קוד ק שאני מסתכל על testסט ואני אומר אוקיי מה יקרה אם אני אלך לפרודקש קוד ואתה רואה את האיף הזה אני אהפוך אותו לתמיד טר יקשה לי איזשהו טestט מה יקרה אם לא יקשל שום טestט מה זה אומר >> מה אם יקשל שום טסט או שהקוד הזה מותר או שחסר >> או שחסר טest זה בטוח אומר משהו אבל הנה עוד דבר חשוב כשמדברים על אינטראקציה אנושית אני אומר מה יקרה אם אני אעשה את הדבר הזה ואני מסתכל על הפנים של הבן אדם שכתב את הקוד [\[24:39\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1479s) עכשיו אם הבן אדם הזה עשה את זה בTD בצורה הפשוטה ביותר הוא הגיד לי בביטחון מחלט לא יקשה לך לבחוש שניטסט עכשיו אם הבן אדם לא כתב את זה בטd זה מאוד פשוט הוא יאסס הוא יגיד נראה לי שמשהו יתקשר עכשיו זה לא דרך לצלוב מישהו זה דרך קצת להבין מה באמת קורה גם להראות ש שנורא אכפת לך מהקוד של הבן אדם זה לא סתם אתה נכנס לטיני טilס לדברים הכי הכי קטנים שחשוב לך איך שדברים כתובים זה לא סתם שפיצ'ר עובד זה גם קשור לקראפטנשיפ למקצוענות [\[25:17\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1517s) להגיד שאצלנו יש איזשהו קול דיבור שאנחנו לא מוותרים עליו שאני לא מוותר עליו אישית אז לראות את הפנים של הבן אדם במה שאני עושה זה נותן לי המון המון מידע. זה לא אומר שאני אעשה משהו עם המידע הזה, אז זה בכלל אומר לי משהו לכיוון הבאות, לפיצ'רים הבאים שאני אבדוק. יש הבדל גדול מאוד בהתחתו של בן אדם שעשה משהו בTD לבין בן אדם שעשה טestטים אחרי מבחינת הביטחון שלו שמשהו ייפול או לא ייפול. זה דבר מאוד נחמד. אם אני עכשיו אלך לכל אחד מכם אני אגיד מה יקרה אם אני אשנה את העיף הזה? [\[25:47\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1547s) כולכם תגידו לי בביטחון. אין שום מצב שזה לא יעבוד. אבל יכול להיות שאולי איזה זוג אחד פה שכתב כבר דברים regular expression ולinkקר יגיד מה לא בטוח שזה ייפול לא בטוח שיפול ב איזשהו כסף בגלל שככל שפותרים דברים בצורה יותר מסובכת הביטחון בזה שכל הדברים באמת נבדקים יורד אבל הרצון שדברים יעבדו מאוד גדול ולכן המנחות נוטים לעשות דברים בצורן מאוד מאוד ג'נרית אז אמרתי להימנע מלוגיקה בטestטים הנה דוגמה לטestטים לוגיקה [\[26:21\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1581s) כולכם צריכים לקרוא את זה. אוקיי, כשאני מסתכל, זה test אמיתי, כמובן, הטestט הזה הוא ממיקרוסופט unity source cod. כשאני מסתכל על test, הדבר הראשון שאני מסתכל זה השם של הtest. Select constructor with two parameters. חסר משהו בשם? מה? ‏Behav תשימו לב כמה זה חשוב. [\[26:52\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1612s) אם אני לא יודע מה אמור לקרות, אני עכשיו צריך לקרוא את הקוד של הטest, לחפש את האסרטים, לראות שיש לי פה את הדברים האלה. אז קודם כל הדבר הראשון שאני שם לב זה שיש לי פה לוגיקה. אתם רואים את הלולאה הזאת? לולאה כזאת זה לוגיקה. לולאה מחר יכולה להישבר בדרך כלל בנולאות מלבד פוריג', אבל גם פורי יכול להיות בו איזשהו בד שאתה לא רוצה לעבור על כל האייטמים. יש לי פה גם כמה אסרטים [\[27:23\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1643s) עכשיו בואו תשימו לב לדברים שקורים פה יש לי פה אריקול 2 על paramמטר keys count ואז יש לי עוד פעם אריק 2 על הזנ אוקיי שני הסרטים האלה הם אותו דבר זאת אומרת שניהם מקבלים את הלנס ועושים את הרגול שתי איך איך מגיעים למצב כזה אם אני מסתכל על על test ואני רואה דבר כזה אני צריך להתחיל להתנהג קצת כמו שרלו ולנסות להבין איך זה הגיע למצב הזה וזה חשוב מאוד כדי להבין איך להבין איך זה דבר כזה מגיע למצב כזה כי זה אומר המון על מה כדאי לעשות כדי לפתור את זה כדי שזה לא יקרה יותר [\[28:05\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1685s) איך לדעתכם אם זה מגיע למצב כזה >> מי ששינה את הפונקציה get parametטרסיז ורצה לבדוק אתה שכו כבר עוסרת לזה קטע אחרון פשוט נוסף אחרי זה >> הקטע אחרון נוסף אחרי זה >> ומתי שהוא קיז לא היה שתיים אז עשה עליו אסרט או יש פה כבר אסרט >> כן >> הוא לא שם לב לזה >> הוא לא שם לב לזה זאת אומרת שהוא לא כתב את הקוד הזה >> מישהו אחר עושה >> שני אנשים כתבו את הטestט הזה לפחות אוקיי זה מגיע למצב כזה כששני אנשים עורדים על הקוד הזה ואף אחד לא מדבר עם אף אחד אחר אז מישהו בא מסתכל על הקוד [\[28:39\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1719s) אם קשה לקרוא את הטestט אז רוב הסיכויים שאנשים פשוט יוסיפו את את מה שהם חושבים שהוא חשוב ובכלל בכלל לא ישימו על שום דבר אחר שקיים בטסטופשוט יניחו שהדברים האחרים הם סוג של לגסי כבר אז אם קשה לקרוא את הטest אנשים לא ידרחו לקרוא אותו עכשיו asert policy is correct תשימו לב יש פה איזשהו help ftion שלכל אחד מהקיז הוא בודק יש לו איזשהוט בפנים [\[29:12\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1752s) איזה מהאסרטים הוא החשוב לדעתכם שהפולicy הוא קורקט או שיש לנו שני casספולסי מה >> הפולסי >> פוליס אז למה צריך את האחרים כאילו אחר >> כדי שהפוריץ לא יעוף >> שהפוריץ' לא יעוף הפוריד לא יעוף אם יש לך רק אחד בתוך הפ >> הוא בודק שני דברים ואתה test פשוט הוא בודק שני result שימו לב יש פה שני result אחד זה שקיבלתי באמת שניים ממשהו והשני זה גם שיש לי קורק בינתן משהו שני results ואז מה קורה אם מחר יש לי רק אחד זה לעולם לא יבדק. [\[29:48\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1788s) בסדר? וזה חשוב לי לדעת את זה. אז כמו רופא שמקבל מישהו לאבחון והמישהו הזה אומר לו רק חצי מהסימפטומים שלו, יכול להיות שהוא יתן את התרופה הלא נכונה, יחבש את הבג במקום הלא נכון, ינסה לתקן את זה ואז זה יעבור ואז זה יקשל. עכשיו נשאל את השאלה האם זה תמיד נכשל או שזה נכשל רק בגלל התיקון שלך. אוקיי? ואז יכול להיות מרדף די מעצבן בנושא הזה. אז דבר ראשון זה להפריד את זה לשני טestטים. דבר שני זה להתפטר מהנולאה הזאת. אני לא צריך את הלולאה הזאת. [\[30:18\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1818s) אני יודע שיש לי רק שניים. אין שום מה לכתוב פה שני שתי קריאות לפוליסי. ברוב הסיפורים שאני לא צריך לבדוק אפילו שניים בעינתן כי בענתן אחד אני יכול לבדוק שהפוליסי קורק. זה אנזלט נפרד. אם אני יודע שהפוליסי הוא קורק לכל אחד שנכנס עכשיו אני יכול לבדוק שיש לי שניים. אני יכול לבדוק שהפוליסי יה קורקט רק כדי להרגיש אולי יותר בנוח עם הכל. וזה גם משהו שאתם תמצאים את עצמכם עושים הרבה. לפעמים אתם תראו שאתם מוסיפים טestטים שהם אמורים לעבור, הם לא אמורים להיקשר, [\[30:48\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1848s) אבל הם ירמו לכם להרגיש יותר טוב עם הקוד. זה בסדר גמור להוסיף כאלה טestטים. אלה טestטים שבעצם עוזרים לכם לוודא שאתם יכולים לעשות דליבר לקוד הזה. בסדר גמור. רק תוודו שהשמות שלהם נכונים ושאתם לפעמים אתם יכולים לשים את זה ממש בקובץ נפרד והקובץ הזה יכול לבוא ולהגיד או advanceed usage או משהו בסגנון כדי להראות לקורה שפה לא מדובר במשהו שנעשה בtd אלא הוא מדובר במשהו שהוא מראה איזשהו סנר קצת יותר אמיתי עם הקוד [\[31:25\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1885s) הטestטים האלה הם לא טestטים שהם לא חשובים אבל חשוב מאוד לשים אותם במקום שבו אתה מבין שהטestטים האלה לא מייצ מיצגים את הסקס הכי פשוט מאצגים casי שהוא כבר יותר מסובך בעינתן שכל הטestטים האחרים עוברים סוג של כביכול acceptט test אבל הכל בזיכרון בלי דברים שאין לך שליטה שאין לך שליטה כביכול pr אינטגרש שאלות לגבי זה שאלה >> כן [\[31:56\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1916s) העניין של הסימת אסרט אחד בכלל זה לא יכול להגיע למצב שבו יהנו לנו הרבה מאוד דקות כפול בטסטי קוד כפול בטסטים אה אוקיי אז לגבי קוד כפול בטסטים אז דברים כמו הלפר מט שמייצרים לך את האובייקט אבל אז אבל אז הופך לטסט לא קריפר שקורה לאפר כאילו כמו שאמרת זה ביום הראשון ש הטסט מצד שבו אני יכול לקרוא אותו דבר ככה אחת >> אבל אם יש לי הלפר שקורא לאלפר שקורא לאלפר אז אז הקוד הוא לא כפול אבל קודם כל אחד אני לא זוכר רמי רמי צודק שאם יש לי הלפרים יש לי מגלבל של הלפרים אז זה לא קרים אני בל מנסה שתהיה לי רק שכבה אחת של הלפרים שאני קורא למטסט ולא אחד שקורא לשני כי אחרת זה באמת בלתי קרי [\[32:39\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1959s) ולפעמים אני אפילו מסכים שיהיה לי דפליקיש בטestי כי יותר חשוב לקריאות מאשר mainity של testing זה חשוב קריאות בלי קריאות זה לא משנה כמה הטest שלי הוא מינable אם אף אחד לא יכול להבין אותו אחד הדברים הכי מסובכים שראיתי זהטestטים שיש להם cles עם שלוש חבות גמ ככה שאתה רואה איזשהו טestט קלאס ולכל טestט מאחורה קורים 350,000 דברים ורק להבין את כל הסייד אפקט של כל טestט [\[33:11\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=1991s) זה כמעט בלתי אפשרי אז הטestטים הם באמת היו מאוד מינטינable ומבחינת אינג'נירנג הם ממש ממש היו יפים אפשר להגיד מבחינת ההבנה של מה להזזל קורה שם היית רואה איזשהו אסרט מאוד בסיסי כאשר למטה הוא היה עושה עוד 50 אסרטים אחרים ובסטאפ שבכלל לא היית רואה הוא היה בבייס קלאס היו קוראים עוד 30 דברים כמו לשים מלא [מוקים](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)") [וסטאבים](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)") וכל מיני דברים כאלה אז הקריאות הייתה גרועה מאוד ולכן כל פעם שמישהו רצה להוסיף טestטים חדשים היה נורא מסובך להוסיף טestטים חדשים כי כמעט אף אחד לא הכיר את הפרוטוקול של איך להוסיף טestטים מה יש בביס האלה כי האינפסטראקטור של הטestטים היה כל כך מסובך הוא היה אובר engineר שהיה מאוד קשה למישהו להוסיף טסטים חדשים בלי לשכפל קוד ורק לשים איזה איזשהו קופי משהו פשוט ואז פתאום לקח שאל הוסיף טסט חדש בגלל שכל הדepנen האלה דרשו שימלאו אותם במקום משהו שאתה יכול לעשות סטריפ לקרוא אותו ולגמור עניין אזדפליקישן [\[34:10\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=2050s) ברמה מסוימת זה משהו שלדעתי הוא בסדר אם זה על חשבון קריאות זאת אומרת אם אני צריך לבחור בין דופליקיש לבין קריאות אני אבחר קריאות לא אבל זה לא רק נגיד הבדיקה הזאתי קודם כל בודק שהקונסטקצור נכון ורק אז מהקיז שלו נכון עכשיו אם אני עושה את זה כשתי טestטים יפדים אז מספיק שהקונסטקטור יקשל ואז זה קבל שתי טסים שכשלו ואז זה כמו שכאילו תראות ביפול פתאום 15 אקספו שגיעות קופילצ לא קשורות אחד לשנייה אם היא תקבל רק את השגיעה הראשונה שבגללה אתה יודע כל הידה ביותר הכריף השגיעות היו יותר קירות >> אנחנו נדבר על זה בהמשך אבל בגדול [\[34:45\]](https://www.youtube.com/watch?v=L7m3myFfWMk&t=2085s) שני טestטים האלה הייתי משאיר אותם את שני הסרטים האלה ביחד תשימו לב ששניהם על אותו אובייקט מתחילים על אותו אובייקט בדרך כלל שיש לך מטיפלסרס על אותו אובייקט אז אז אכפת לך רק מהראשון שנכל ועל השר כבר לא אכפת לך אבל כשיש לך שני הסרט ## Related - [The pillars of good unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8) · The Art of Unit Testing, 2nd ed., ch. 8 The pillars of good unit tests: trustworthy, maintainable, readable, the three groups the lesson organizes rules into. - [Mixing unit tests and flaky integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7) · The Art of Unit Testing, 3rd ed., ch. 7 Book section on mixing unit tests and flaky integration tests, why the lesson keeps them apart for trust. - [Test Reviews Vs. Code Reviews - Some Helpful Tips](https://osherove.com/blog/2007/3/13/test-reviews-vs-code-reviews-some-helpful-tips.html) · osherove.com Tips on reviewing tests instead of code, matching the advice to start code reviews from the tests. - [Test Review #3 – Unity](https://osherove.com/blog/2009/3/23/test-review-3-unity.html) · osherove.com Roy's video review of Microsoft Unity's tests, the same codebase whose test is critiqued in this lesson. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8), ch. 8 - [How can we know we don’t have bugs in our tests?](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11), ch. 11 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [How to know you trust a test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134), ch. 7 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 - [Keep tests DRY](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_161), ch. 8 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 #### The Art of Unit Testing, 2nd ed. - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1), ch. 1 - [Writing trustworthy tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec1), ch. 8 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec6), ch. 1 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec3), ch. 1 #### osherove.com - [How Do You Explain Pair Programming?](https://osherove.com/blog/2005/4/3/how-do-you-explain-pair-programming.html) - [Test Coverage and testing angles](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html) - [Try to avoid multiple asserts in a single unit test](https://osherove.com/blog/2005/4/14/try-to-avoid-multiple-asserts-in-a-single-unit-test.html) [Previous lesson Day 2 Summary](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/day-2-summary/) [Next lesson Best Practices Continued](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/best-practices-continued/) --- title: "Best Practices Continued" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/best-practices-continued.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/best-practices-continued/" tags: [] author: "Roy Osherove" description: "Lesson 17 of 22 in TDD in .NET in Hebrew (Day 3 - Unit Testing Practices), 25:20. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Best Practices Continued 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 3 - Unit Testing Practices Lesson 17 of 22 Duration: 25:20 [Watch on YouTube](https://www.youtube.com/watch?v=50LeVOHrplA) Spoken in Hebrew ## In this lesson Roy Osherove advises against tests that depend on each other's order and against [magic numbers](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_169 "Magic values and naming variables (The Art of Unit Testing, 3rd ed., ch. 9)") such as a 37 in the Unity tests, preferring the simplest value or a named variable. He shows an [ASP.NET MVC](https://osherove.com/blog/2009/3/21/test-review-2-aspnet-mvc-unit-tests.html "Test Review #2 – ASP.NET MVC Unit Tests (osherove.com)") [test helper](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6 "Building a test API for your application (The Art of Unit Testing, 2nd ed., ch. 7)") that builds a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") HTTP context with [Moq](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5 "Current isolation frameworks for .NET (The Art of Unit Testing, 2nd ed., ch. 5)") and is full of ifs, suggests overloads instead, and wants [expected values hard-coded](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_142 "Logic in asserts: Creating dynamic expected values (The Art of Unit Testing, 3rd ed., ch. 7)") rather than computed, so a production bug is not repeated in the test. Reviewing a [NerdDinner](https://osherove.com/blog/2009/3/20/test-review-1-nerddinner.html "Test Review #1 - NerdDinner (osherove.com)") test named "should be valid when all properties correct", the group debates splitting it into [one test per validation rule](https://osherove.com/blog/2011/2/9/multiple-mocks-asserts-and-hidden-results.html "Multiple mocks, asserts, and hidden results (osherove.com)"). ## Transcript 3,677 words [\[00:03\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=3s) על שני אובייקטים שונים זהפל result ואז אכפת לך אז זה לא איזשהו משהו דתי שצריך להגיד עם הסרט אחד בקטקסט אבל זה קונספט אחד שנמצאת בקטסט אדלט אחד אוקיי אז אז אם אני רואה אובייקט אחד בשני הסרטים מתחיל הייתי אני אגיד לך אומר זה לא נורא אני בודק person name ו number ואם הני נכשל אז מתלכתחילה כבר כל הפרסון לא בסדר אז זה בסדר זה לא כזה נורא אבל אם אני רואה person A נקודה A name ופר B נame ואז יכול להיות ששני אנשים זה כבר משהו שונה או מנג'ר כן באופן כל יותר כמה מה שרב שואל מספרן אותי [\[00:39\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=39s) אה יש איזשהי דרך להגיד depפendנen testing להגיד שאם test אחד נחשל אל תמשיך הלאה או תראה לי רק את הראשון אני בדרך כלל ממליץ שלו זה לא יהיה אני יש דרך במסט test להגיד שטestטים יראו אותו בסדר מסוים אבל לא dependency בין testing אוקיי עכשיו הסיבה היא שאני לא ממליץ על דבר כזה זה בגלל ש המינטנבity שלהם נפגע מאוד מחר אתה מזיז test אפילו או אתה מוחק אותו ופתאום טestט אחר נחשב שבכלל לא חשבת שהוא קשור לזה ולכות שהטestט הזה הוא עדיין בודק אין רזלט אחר אם הטestטים האלה יכולים לראות בנפרד אז אני מעדיף את זה עכשיו פה הנימינג מאוד חשוב אני שובר פיצ'ר וחמישה טestטים נכשלים [\[01:25\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=85s) אוקיי אני מסתכל על השמות שלהם ואני רואה וואלה הסצנריו שלהם שונה לחלוטין או הendat expted behav יכול להיות שיש לי חמישה behaviס לפח להבין את זה אז כן יש סיבה שכל הטסים נמצאים שם אני מעדיף שיהיה לי חמישה טסים שנכשנים מאשר אף אחד שלא נכשל בסדר ופה באמת יש לך חמישה שנכשלים אם אתה רוצה לדעת לאיזה להתחיל לדבק השמות מאוד חשובים פה כי אתה רואה שיש אחד עם הסנריו הכי פשוט זה זה שאתה תתחיל איתו בסדר [\[01:57\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=117s) עוד שאלות יש עוד דברים שאתם לא אוהבים בטסט הזה? אה, אחלה. >> למה 37? כאילו 37 הרוצח הסדרתי יבוא. כן. >> לא ברור לי. הR אקל הראשון מה הוא משווה? הוא משווה טיפים >> לא R equal משווה vales. אם אתה רוצה להשוות טיפים אז אתה עושה Rame זאת אומרת לוודא שהיance הזה והאינס הזה זה אותו אינסטנס. כן. אבל זה לא קונסטר [\[02:29\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=149s) משהו לא ברור >> הקונסטרקטור infו זה משהו שרפלקlectionקש מחזיר unity הוא מערכת שמשתמשת הרבה ברפלקשן אז בעינתן שאתה מוצא משהו אתה מקבל חזרה את המידע הנכון הוא עדיין בודק את הוליו של הקונסטרקטור אינפו יכול להיות לך שני קונסטרקטור אינפו שמתארים את אותו קונסטקטור בסדר אמ בעייתי מאוד כי אף אחד לא יודע מה זה 37 זה יכול להביא לצרות מאוד מאוד מעניינות. בן אדם כותב טestט חדש והוא אומר איך מישהו כבר כתב טסט? [\[03:00\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=180s) אה אני רואה שהם ישתמשו בו ב-3 אני לא יודע מה זה אומר אז אני אעשה לזה קופיט אני נראה שזה חשוב אז אנשים צריכים להבין לי משהו חשוב ואז פתאום אתם רואים את 37 מופיע במאות טestטים בקוד של הקולי זה כמות הפונקציות באיזשהו קלאס אולי זה כמות הקראקטר באיזשהו סטרים אולי זה כמות הפעמים של משהו צריך לעבור איפשהו אולי זה איזשהו קונסט במערכת שלא משתמשים בקונסט שלו אם לא יודעים אז מתחילים פתאום אתם מתחילים לחפש 37 בכל הזו ס אז אתם רואים מאוד טסים את זה בשום מקום אחר [\[03:34\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=214s) ולפעמים פשוט אין שום דרך לגלות את זה אז לא להשים מספרים כאלה במקום זה לשים או את המספר הכי פשוט או לתת שם של משתנה שאומרס number מאוד חשוב בטestטים להגיד מה לא חשוב בסדר להגיד למישהו אל תתרכז בזה זה לא ה זה לא האישue פה בגלל זה גם פה הסנר הוא מאוד חשוב זה הפטד resultל אם יש לי את כל הסרטים האלה והיה לי פה איזשהו expectectד resultלט נורמלי כי יודע איזה מהסרטים חשוב אבל בדרך כלל אם יש לי מטיפלט שבודקים כמה דברים אז זה מאוד הגיוני שיהיה לי קשה מאוד לפתור expectד resultלט [\[04:10\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=250s) ז ככל שאתם בודקים יותר דברים ככה לתת שם לטest יהיה הרבה יותר קשה כי השם יצטריך להיות הרבה יותר גנר הנה עוד דוגמה ללוגיקה זה מ-ASP.NET MVC [ASP.NET MVC](https://osherove.com/blog/2009/3/21/test-review-2-aspnet-mvc-unit-tests.html "Test Review #2 – ASP.NET MVC Unit Tests (osherove.com)") זה לא test זה helper methodד של test הלפרer metוד הזה משתמש [\[04:40\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=280s) במק [Moq](https://osherove.com/blog/2012/6/27/the-future-of-isolation-frameworks-and-how-moq-isnt-it-for-n.html "The future of Isolation frameworks, and how Moq isn't it (for now) (osherove.com)") ומה שהוא עושה זה הוא הלר שמחזיר [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") htp contct אחד הדברים האיפים שהם עשו בhp. ‏MVC זה הם עשוי את הזign קצת יותר testable זאת אומרת אתה יכול לעשות fake לhtpx base ורוב הפונקציות שם הם virטס מה אני אומר שאתה יכול להחזיר מה שאתה רוצה מquest application וכולי אז הלפר הזה testים יכולים לקרוא לו ולקנפג איך נראה הHT קנטקסט שלהם [\[05:11\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=311s) אז כל הבדיקות פה הן בעצם לוגיקות אם מישהו שלי לי את הפרמטר הזה אז תשתמש בו כדי להחזיר אפליקיש כנל גם לגבי הפרמטר הזה והפרמטר הזה וככה עוד בהמשך הפונקציה. עכשיו הטענה שלי היא שכל הלוגיקות האלה אפשר להתפטר מהם ועדיף להיפתר מהם כמה שיותר מהר כי מספיק לי באג אחד קטן שיש לי גדול במקום גדול שווה או גדול שווה במקום גדול מ שפתאום חלק מהטestטים מתחילים לעבור וחלק מהם מתחילים להיקשל או שהטestט עובר ואני מניח שהכל בסדר אבל הוא היה אמור להיכשל או הטestט נכשל והכל בסדר אבל לא היה אמור לעבור [\[05:55\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=355s) כי למצוא את הבאג בטestטים זה ממש קשה למצוא את הבאג בהלפר של הטestטים זה ממש ממש באסה כמו שגיליתי בשבוע שעבר נזכרתי עוד פעם כמה זה באסה כי בדיוק מה שהיה לנו זה הלפרer metod שמגנרט לוח של ופה זה הלפר מוד שמגנרate htp contטקס אם הוא מקנפג אותו בצורה לא נכונה אתה מחפש איזשהו בג שבכלל לא קיים בפרודקש זה יכול לבזבז המון זמן אז איך נפטרים מזה אחת הדרכים הכיות זה לעשות ורסיה של htpקטeקסט פר פרמטר זאת אומרת לעשות אוברלים ואז אין שום שאלה אם להשתמש בפרמטר או לאפונקציה [\[06:30\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=390s) הזאת תמיד משתמשים בפרמטר הזה אתה לא רוצה את הפרמטר תקרא לפונקציה אחרת אוקיי ואז אתם מפטרים מכל האיפים האלה וזה יעבד כעשיתי קוד רוw ראיתי שרק שני טestטים משמשים בפונקציה הזאת אז בכלל לא היה צריך את כל הלוגיקה עשו לזה overרing לכתחילה שאלות כן >> באופן כללי פנ כמו שיש לנו זה לא אפשר ש לעשות כאילו נגיד אסמלי של הלפר ליוט testing נגיד בקונטקסט מסוים ואז להעריץ לו גם בליקות לכתוב לו באמת testסטים ואז יהיה אפשר להשתמש בזה הדבר היחיד שבאב הייתי אומר לפעמים אתה צריך פילפרים מסובכים וואלה תכתוב להם טestטים [\[07:12\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=432s) בדיעבד היום אני אכתוב טestטים לזה של ללוח של הגוב אני לא אשתמש בטסטים הקימים שלי כדי לבד שהוא עובד כי אתה צריך לסמוך על זה שהוא עובד כבר >> כלומר להפריד את זה ול >> אם אין ברירה אז אין ברירה וגם זה צריך לכתוב טסטר כי ההשפעה של בג בזה היא הרבה יותר גדולה מההשפעה של בגוד של קודם כי זה משפיע הרבה טestטים שמשפיעים על פודק של ואז כל הטסט של הרבה אבל בדרך כלל אתם לא תסתרכו דברים מסובכים זה חשוב מאוד 99% מהזמן אתם לא תסתחו דברים מסובכים בהלפר metodס מתי זה כן נהיה מסובך הפעם פעמים יחות שראיתי שזה נהיה מסובך זה כשאתם מתחילים לכתוב דומיין specific langו לקונפיגורציה של הטest לפעמים צריך את זה כבר מתחיל להיות מסובך. [\[07:55\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=475s) זאת אומרת אתם כותבים איזשהו DSL שבו אתם אומרים אני רוצה אובייקט שנראה ככה ועם כל הדברים האלה ושמה וואלה כבר אתם מתחילים לכתוב הרבה comון cדde ושם צריך כי אחרת אתם מקמים אוי שמגונפג לא נכון וכל הטestים שלכם מתכתחילה הם כבר לא נכונים אבל לבדוק את זה זה זאת אומרת להבין שזאת הבעיה אז מאוד קשה בהתחלה עוד שאלות אוקיי עוד דברים חשובים שקורים כל הזמן בטestטים כדי לסמו מוך עליהם אני מוודא שאין לי לוגיקה [\[08:28\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=508s) בexpected values. זאת אומרת תמיד ב expectect values אני מנסה לוודא שאני אף פעם לא מייצר אותו בצורה דינמית כי אם אני מייצר את הxpectד val בצורה דינamמית רוב הסיכויים שאני גם חוזר על production קודם זאת אומרת אם אני מצפה לקבל user + פסיק + פwסיכויים שבprפודקt קודש לי user + פסיק + password ואז אם יש לי באג נגיד שחסר לי ספייס אני משחזר את הבאג הזה בטestטים שלי ואני לעולם לא אמצא אותו הטestטים שלי יעברו זאת אומרת תמיד עדיף לי וectד ‏val בit testing לא בintegration testit testing [\[09:03\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=543s) לקבל hard coded vales expected לקבל את הס כמו שאמור להיות לקבל את ה כמו שאמור להיות וככה להגיד וואלה לא אכפת לי איך משהו מיוצר אכפת לי שהוא נראה ככה בסוף או שהוא מכיל משהו שנראה ככה בסוף ואז מחר האלגוריתם יכול להיות אחרת לגמרי או שאני אגלה הרבה יותר מהר את הבאגש אז אם אתם רואים פלוסים או כל דבר שמיוצר דינמיק בעסרט שלכם בect value תראו אם אתם יכולים לעשות הרקוד את רוב הסיכויים שעדיף שזאת אופציה עדיפה ואם אתם לא יכולים כי אתם כי לא הרבה פעמים אנשים עושים test cases ואז הם מחשבים את הPected value מהtest cas אבל מה שפשוט עושים זה פשוט שולכים גם את הPectate value בtest cas או שעושים result שווה אנחנו בטest [\[09:55\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=595s) זה כמעט אף פעם לא לא הדרך הטובה ביותר לעשות את זה ביטר וואלה תעשו מה שאתם רוצים יש לי את ההפייפס שעובד ועליו זה השלט שלי ואחרי זה אני יכול לבדוק עליו עוד מיליון דברים שאלות אוקיי כדי לסמוך על הטestטים שלי אני מוודא שתמיד הטestטים שלי הם אותם testים אז אני לא משתמש בדברים שמשתנים time now אני לא משתמש בו בטestטים שלי אני אני תמיד משתמש באיזשהו הרדקודיט והסיבה היא שכל פעם שאני אריץ את זה אני רוצה שזה יהיה בדיוק אותו טס אותו טestט כל דברים כל הדברים שקשורים מטקם [\[10:30\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=630s) וכולי זה דברים שאני מעדיף לעשות הרדקוד אני לא משתמש בפרדים אני לוקח את הלוגיקה שרד אמור להריץ ואני אבדוק אותה כunity of work 1 הנה דוגמה לטest זה מנדנר [NerdDinner](https://osherove.com/blog/2009/3/20/test-review-1-nerddinner.html "Test Review #1 - NerdDinner (osherove.com)") זה אחד הפרויקטים לדוגמה שמייקרוסופט הוציא הראשונים של שימוש ASP.NET MVC [\[11:05\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=665s) אוקיי מה אתם חושבים על הטסט אני אשמח לשמוע למה יש הרבה קווים תחתונים שק של המדה שאלה מעניינת הקווים התחתונים זה סוג של תת לא תת תרבות אלא תרבותסבקצר אבל זה לא תרבות רעה אלא תתרבות שקיימת בעולם של היוטestים אנשים שבאו מעולם האל.net נט יצאו לעולם הרובי וחזרו בעולם הרובי נורא נפוץ לכתוב שמות של טסטים עם אנדרספורים בלי כדי שזה יראה קצת כמו משפט בעולם הרוב והדרך שבה רוב הטestטים או הספקטים נכתבים שאתה אומר משהו ואז אתה נותן סטרינ והסטרינג הזה מתאר מה שהטest אמור לבדוק בדוטנט אין את היכולת הזאת אוין יכולת פשוטה לעשות את זה אז יש אה פשוט תבות של מה שאנשים שפשוט ותים טestי כמשפט ופשוט מפרידים מילים באנדרס [\[12:01\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=721s) זה לא קשור ש בכלל על קנשנו מדברים עליו זה פשוט הדרך לכתוב משפט שיהיה קרי עכשיו במקום הקמלס יש אפילו פלאגין שאתה נותן לו strרים ואוטומטית הופך אותו למשהו עם אנדרס זה אוקיי אז ונתן זה שאלות ותגובות לגבי הטסט כל הסטריים מעניינים מדי מעניינים מדי >> טוב טייטל אני לא בטוח >> בסדר אבל הוסט בעסק סקות גום [\[12:32\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=752s) בעיה 92 >> כן >> וגם הט הוא גם כן בעייתי time now זה אומר שהטest הזה משתנה כל הזמן כל הקנactפ טוב קודם כל תתחילו מהשם תשימו לב should be valid when all properties correct what the fuck does that mean all properties האם אלה כל הpties correctקט בהם מהקורקט בטלפון הזה שיש בו את הקווים כמות הקטרס מה מה קורה מה קורק בhosted by [\[13:04\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=784s) שהוא שהוא קיס אין שום דרך לדעת מה קורה בלטוד ולונדיטוד אתה גם לא תדע מה קרוב לזה להיות לא וליד >> נכון והשאלה אם יש טestטים הפוכים לזה התשובה היא לא יש טestט אחד שגם שם זה נראה בערך רחוק מזה יש לך איזה משהו ואחד מהם לא קורה אמ אז is true is valid אז מה בעצם הייתם עושים עם הטest הזה לדעתכם? [\[13:35\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=815s) מפרקים אותו. מפרקים אותוכמה טestטים >> עברו כל propפרטי לפחות טestט אחד או שניים נכון >> 1 2 3 4 5 6 7 תשעה טestטים שונים לפחות >> מה אבל בספר שזה גם לא בודק את זה ככה זה בודק בטח טלפון או מייל כל אחד זה פדיקה שנהכל >> ספציפית זה בגלל שאם זה mVC אז הבדיקה היא באמת סוג מסוים של בדיקה כלומר valid זה משהו שהוא חלק מMVC כן אז הדיקה כאן מלכתחילה היא לא אני לא חושב שהיא נכונה בקונטקסט הלי צריכה לבדוק את העניין של הולידטורים עצמם נגיד require validat compare validat [\[14:17\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=857s) זאת אומרת במקום לבדוק את זה אבל תחשבו שזה סוג שלגרשט אח שכל הליידור בגדול test לכל ולידור או אני הרבה יותר הייתי מעדיף לא אכפת לי מה זה ולידור ומה זה ומחר יהיה לי מגנון אחר לעשות ולידציה זה שהalידור עובד זה לא אומר שיד אתה מסכים איתי זה implementationil ולכן מה שהייתי מעדיף זה שכמשתמש אני אבדוק משהו עם אריזל שאכפת לי ממנו כמשתמש אז כמשתמש אני רוצה שיהיה לי טסט שאומר אני מייצר דינר שבו הכל ולידי מלבד [\[14:54\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=894s) אחד ואני רוצה לראות שזה אינולד ואז הכל ולידי כולל האחד הזה ואז זה וליד וככה לכל אחד מהדברים האלה עכשיו איך עושים איך מייצרים טestט כזה איך מייצרים טestט שבו יש לי תשעה סוגי ולידציה ואני כל פעם רוצה לוודא שכל השאר הם ולידים יכול להיות שפה ליצור את כל הולידים זה מאוד קל אבל לפעמים ליצור את כל הלי val מאוד מסובך ואז לכתוב את הטest נהיה מאוד מסובך אחת הטכניקות שאני אוהב זה להשתמש בקס שהוא testable ולעשות לכל validation functionנש איזשהוטל מפוד שמחזיר בוליה [\[15:30\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=930s) ואז בtestable אני פשוט עושה פגים מה כל אחד מחזיר מלבד אחד שאני לא מממש תחשבו על זה שיהיה לי is title valse שזה protected virtual is desption valestable שבו אני אומר תראה בנתן שdcription ו כולם מחזיריםט י אתה משתמש בליטור האמיתי או שהוא מחזירפse האם is valid באמת מחזירפse זאת אומרת אני בודק את האלגוריתם שמשתמש בכל הalidation [\[16:02\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=962s) יש לי הרבה דרכים צריכים לבדוק את זה אבל הרבה צריכים להשתמש בזה האם הולידטור זה אמיתיים או בלי וזה כבר החלטה שלי אבל מבחינת ההפרדה הפרדת רשויות פה הרבה פעמים האקסטרctט לאoverיט מה שעשינו פעם קודמת עובד מאוד יפה והטest הוא גם מאוד קרי אני מייצר איזשהו testable דינר ואני אומר זה הולך להיות פס זהפס זהפס אה והדבר הזה אני הולך לבדוק אותו ופתאום זה ממש נראה קל וקרי והרבה פעמים בלגסיק עוד מגיעים למצבים כן יש במצב הזה לא יותר פשוט נגיד ניקח את אותו קוד שיש לנו כאן ולניח שאני כן יודע מה זה סיטואציה שהיא אמורה לעבור נניח את כל דבר ולידי אז זה לא דוגמה שאולי כן יהיה לך מן לעשות כאן פשוט מולטיפליי הסרט פשוט כל פעם לערוך שדה לעשות ואז אני יודע בסופו של דבר אם זה ולילי או לא ולילי ויתי זה ביחידת קוד אחד יש לי קריאה אוקיי מה אתם חושבים [\[16:58\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=1018s) מה אתם חושבים אם הוא היה עושה את זה זה היה דבר טוב או לא >> לא >> למה לא >> קשה לתחזק את זה קשה להבין את זה זה מחבר >> קשה לחזק את זה לא בכללפ >> קשה להבין לא השלישי אף וכל היתר את זה לא נבחים >> אבל זה לא בעיה שזה אף כי גם הבדיקה שלך אם זה בלילים אתה רואה בדיוק בי מקום >> הוא אמר בעצמו שעל אותו אובייקט עושה כמה עש בדיוק זה אותו אובייקט זה נראה לי מאוד עכיוני ויותר יותר ברור מאשר לבנות המון מתנות נוספות ופלייקות זה קרי קצר ומאוד מעניין >> אוקיי של המני מה אתם חושבים? [\[17:31\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=1051s) יש עוד מישהו עם מחשבות לגבי הדבר הזה? >> כן. ספציפית בגלל שהקוד הזה בודק את בודק את המודל פה ו בMVC לדוגמה כנראה שיש על הקונטקטפון זה הדוגמה שהבאת אז יש רגקס שבודק את הקונטקט פון הזה מה שהייתי מוסיף פה לפי לפי הטestט הזה אי אפשר לדעת מה נחשב אפשר לדעת שזה עבר או לא עבר על אי אפשר לדעת מה >> הייתי מוסיף את ה את הארור עצמו זאת אומרת מה מהם לא עבר כבר >> אוקיי >> מבחינתי זה כאילו נראה לי פחות אינטואיטיבי לקחת את עכשיו לפצל את זה לשרה טestטים שכל בכל טestט אתה מאתחל את הקונסטרקטור ומשהו אחד אתה מחליט לא נכון שיש לך את הבדיקות עצמם על ה [\[18:20\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=1100s) על הפרט של המודל זאת אומרתק contנטרctפ בודק לtitט יכול לבדוק nonנג number או משהו כזה >> אז בעצם מה שאתם רואים זה שהטest הזה דווקא בסדר הוא במקרה זה לא בסדר כי הוא לא עונה על השאלה אם היו מוסיפים לו עוד הסרטים ומנסים להכשיל אותו אז הוא היה תחשוב על זה שבעצם הוא תשעה הסרטים בבת אחת הפרטיזם כולם >> כן אבל זה אני אומר נגיד הדבר הזה אני יודע שזה דבר שהוא תקן שהוא עובד הייתי אולי גם נותן לשמות שיהיה ברור שזה עובד ואז הייתי מוסיף עוד הסרטים שמכשילים את זה שדה שדה [\[18:56\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=1136s) ומטפים >> זאת אומרת יהיה לך הסרטים זאת אומרת לייצר דינר חדש עם סדות שונים >> לא לא לייצר גם חדש לעשות סט לשד >> לעשות סט לשד >> ואז לבדוק סבבה אה אני אשר להם נגיד אני חושב שקודם כל חשוב להבין שצריך להפריד פה בין שני דברים אתה אמרת את זה אבל לא נראה שזה מספיק מובן יש לבדוק את האלגוריתם שבודק שכשאחד הזאת נכשל להכשיל את הולידיות שזה לחלוטין עם הסקרקנו שלך אמורים לעשות את זה ויש לבדוק עבור כל שדה את הולידטור הספציפי שלו כאילו אני לא רוצה לערבב בין השניים אני לא רוצה שהוולידיות [\[19:31\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=1171s) של איך שפ אמור להראות בכלל קשור לזה שאני בודק שהזיד איך שהוא מתנהגיד הוא יחזיר טר עם כל השדות שלו מחזירים טר וזה הוא בלטין בפור >> כן הוא בלטין של הפרק אתה לא אתה לא כתבת >> אבל איזיד כבר נבד מבחינת מייקרוסופט כי הוא כבר בודק את כל הפרט >> לא אבל אתה לא יודע איזה ועלות הם מופלים זה פשוט יעשה בודק האם אחרי הזונ קרה המסטרפן שלקשפ number >> קרה מה זה שאם אחרי is valid האם קרה נקרא פונקציה של שבודקת ולידציה של טלפון ושל של 20 >> אה אתה בודק שהפונקציות נקראו של זה הנחת נוס של הפריורק אתה לא צריך לבדוק את זה אני חושב שקלח אין צורך לבדוק את הפריור במק זאת אומרת אם e valid פונקציה שאתם כתבתם exrct over יכול להיות שפתאום יש פה הרבה היגיון אם valונקציה של הפריורק אז יכול להיות שזה יותר קרי לעשות set לכל לכל לכל propפרerטי אבל עדיין אני פוחד שהייתה לי בעיה [\[20:27\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=1227s) שאם הסרט הראשון יחר אז כל האחרים מתחתיו לא רצים כי זה לא סתם propפרerטי לאותו אובייקט כל propפרerטy הוא feature תחשבו על זה שכל propפרerטy feature שאתם יכולים לעבוד עליו ביום נפרד אוקיי זאת אומרת אם אם פיצ'ר אחד נכשל פיצ'רים אחרים יכולים להמשיך לעבור זה לא אותו דבר כמו אם ה אם הבדיקה של הפונבר נכשלה אז כבר לא אכפת לך מכל הבדיקות האחרות כל ולידטור הוא פי בפני עצמו [\[20:59\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=1259s) במקרה הזה אני חושב חושב שלא בטוח שהייתי עושה את כל הסרטים באותו טestט כי יכול להיות שהולידורים האלה משתמשים באיזשהו common cde שאכפת לי מם יכול להיות שהם לא אבל זה פיצ'רים נפרדים גם דרך אגב לגבי אולי הסנריוז אני לא בטוח >> בתרחיש הזה אפקטיבי זה נראה לי הגיוני כי האובייקט הזה הוא אובייקט קטן ו >> אבל זה לא האובייקט שנפדק זה הולידציות על גבי האובייקט וכל אחת מהולידציות היא פיצ'ר נפרד זה לא האובייקט עצמו נכון אתה לא בודק את זבלית [\[21:33\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=1293s) נכון >> אני בודק ש >> אתה בודק את האטריביוט של האובייקט >> נכון >> וכל אטריביוט יכול לתת לך יומיים לפתח אותו פיצ'רים נפרדים חמש דקות >> אני לא פה אני לא בודק אבל פעולה של הולידור עצמו כמו שאני בודק האם הוולידטור מפג נכון כלומר אין כאן בבדיקה של ולידטור בדיקות של ולידטור יש את זה ברמת הפרוק מי שכתב ולידטור צריך לעשות לו בדיקות שהולידטור עובר עובד כאן אני בודק ברמה של האינפט >> ששלחת לו את הפרמטרים הנכון >> כן בוא נגיד בעצפג [\[22:04\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=1324s) נכון ובאמת הוא מגיב נכון לאינפוטים כן >> וזה דווקא לא חושב שזה משהו שהוא מסובך אבל >> אבל עדיין אתה תבדוק על כל הסודות במקביל גם אם יש אה נכון אני בודק אותם במקביל השאלה היא כאן באמת מה אנחנו מדברים על קריאה של לראות האם דינר הוא הוא ולידי או לא ולידי זה המשמעות של הבדיקה עכשיו האם אני צריך לעשות את זה על כל פילד האם כל פילד מצדיק פונקציה משלו השאלה היא כאן יש לוטור משלו [\[22:36\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=1356s) >> אז אמרתי אם הולידטור הוא cumם ולידור שהחלטתי לוגיקה משלו אז הייתי צריך לבדוק את הלוגיקה של הולידטור רק על הולידטור >> אבל אם אתה אתה רוצה לדעת שלכל שדה כאן יש ולידטור אז איך תעשה את זה תעשה עכשיו תשעה ולידטורים דבר ש אם הייתי עושה הייתי עושה תשעה סרטים הייתי עושה יותר כי לעבור כל הסרט אתה בודק גם עם מצב שהוא לא נכון. היה כאן נגיד 20 משהו בסגנון. השאלה היא מה התרחיש שיש לך של הצלחה וכישלון? [\[23:07\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=1387s) האם אתה יכול באמת לפתור את הכל בפרשר אחד או שזה משהו שמורכב את >> לא? אבל אז השאלה זה שוב שואלים אותך אם עכשיו ולידטור אחד נכשל יש 10 אחד מהם אז מה תכן אותו והמשיך כי הבדיקה שלה אם זה ולידי אני לא חוש שהייתי מפרק אותו אז אז בוא רגע נסה את הדמיון הזה ונגיד שאין פה תשובה אחת אחת משמעית אבל הפרמטרים שצריכים להדריך את התוצאה הסופית זה האם זה קרי והאם והאם בעינתן שמשהו נכשל אני עדיין יכול למצוא את הבקות כלומר אני יודע מה נכשל אני יודע מה היה אמור להיות. [\[23:44\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=1424s) זאת אומרת הסרטים מכילים אולי את המסג הנכון והסנריו הנכון. זאת אומרת נגיד לפחות המinמimמum valid vales פה צריכים להיות ולא magic vales. כן אני עדיין לא הייתי מפריד את זה מכיוון שהעלות שלכתוב וואלה עוד אוקיי עוד שלוש שורות קוד ולידטור זאת האמת שטויות. זה לא שזה לא שאתה הולך להדפיס את הדבר הזה או משהו כזה. נראה שבעיקר הוצאה הסופית שיש הבדל בין להגיד דינר לא ולידי לבין להגיד אדרס עכשיו הוא לא ולידי או אדס לבדוק הייתי רוצה לדעת שאם מחר מישהו בא וסאבי תיקן את הרגס של הפונ number אז הטest של הפונ number נכשל לא דינד נכשל [\[24:23\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=1463s) דנרד עדיין אמור לעבור יכול להיות שגם הוא יקשל אבל גם יקשלה של הפור אבל אני רואה שני טסים ישרים ואני אומר לא צריך עכשיו לבדוק את כל הליידורס צריך פשוט לתקן את הפורמ אתה בכל מקדי נותן לך את השגיעה שבין מסתדר נחשב כלומר אתה תראה שדיסקריפש אתה לא תדע אם מסתדר אחר נכשל >> תראה אם יש לך את האיס אז הסרט הזה הראשון שיקשה לאך את לעשות שרוצים מתחתיו >> אם עשיתי את הסרט הראשון הבנת >> כן זה אומר שהאינפוט הראשוני הוא הבנתי >> אוקיי ואז יהיה לך הרבה פחות מידע אז במינימום הייתי מפריד את הוליד ל100 [\[25:00\]](https://www.youtube.com/watch?v=50LeVOHrplA&t=1500s) אוקיי אז זה היה הטסט פשוט לגבי זה היה לגביטסט הדברים הבסיסיים ביותר דברים שמשתנים וכולי אתם רוצים לעשות הפסקה של חמש דקות >> כן מה נעשה >> חמש דקות הפסקה ## Related - [Test Driven Validation Logic with Extract & Override](https://osherove.com/blog/2012/5/16/test-driven-validation-logic-with-extract-override.html) · osherove.com Takes apart the NerdDinner validation test the group debates and rebuilds it test-first, one rule at a time. - [Logic in asserts: Creating dynamic expected values](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_142) · The Art of Unit Testing, 3rd ed., ch. 7 Logic in asserts: dynamic expected values, the reason the lesson wants expected values hard-coded. - [Two different ways to create bad logic in unit tests](https://osherove.com/blog/2010/8/14/two-different-ways-to-create-bad-logic-in-unit-tests.html) · osherove.com Explains production logic repeated in tests, the risk of copying a production bug into the test. - [Magic values and naming variables](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_169) · The Art of Unit Testing, 3rd ed., ch. 9 Magic values and naming variables, as with the unexplained 37 in the Unity tests. - [Test Review #2 – ASP.NET MVC Unit Tests](https://osherove.com/blog/2009/3/21/test-review-2-aspnet-mvc-unit-tests.html) · osherove.com Roy's review of ASP.NET MVC unit tests, the source of the Moq fake HTTP context helper shown here. ### Also linked in this lesson #### The Art of Unit Testing, 2nd ed. - [Building a test API for your application](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec6), ch. 7 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Current isolation frameworks for .NET](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5), ch. 5 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 #### osherove.com - [Test Review #1 - NerdDinner](https://osherove.com/blog/2009/3/20/test-review-1-nerddinner.html) - [Multiple mocks, asserts, and hidden results](https://osherove.com/blog/2011/2/9/multiple-mocks-asserts-and-hidden-results.html) - [The future of Isolation frameworks, and how Moq isn't it (for now)](https://osherove.com/blog/2012/6/27/the-future-of-isolation-frameworks-and-how-moq-isnt-it-for-n.html) [Previous lesson Unit Testing Best Practices](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/unit-testing-best-practices/) [Next lesson Maintainability Practices](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/maintainability-practices/) --- title: "Maintainability Practices" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/maintainability-practices.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/maintainability-practices/" tags: [] author: "Roy Osherove" description: "Lesson 18 of 22 in TDD in .NET in Hebrew (Day 3 - Unit Testing Practices), 34:43. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Maintainability Practices 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 3 - Unit Testing Practices Lesson 18 of 22 Duration: 34:43 [Watch on YouTube](https://www.youtube.com/watch?v=0JEOcZyVw-c) Spoken in Hebrew ## In this lesson Roy Osherove ties [maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8 "Maintainability (The Art of Unit Testing, 3rd ed., ch. 8)") to a [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") that runs from a real [entry point](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18 "Entry points and exit points (The Art of Unit Testing, 3rd ed., ch. 1)") to an [end result](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)"), calling checks on how things are done [overspecification](https://osherove.com/blog/2008/7/12/over-specification-in-tests.html "Over Specification in Tests (osherove.com)"), and wants isolated tests that can run in any order. He reviews an [ASP.NET MVC](https://osherove.com/blog/2009/3/21/test-review-2-aspnet-mvc-unit-tests.html "Test Review #2 – ASP.NET MVC Unit Tests (osherove.com)") test that loops over link overloads, which hides which overload failed, and a [Moq](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5 "Current isolation frameworks for .NET (The Art of Unit Testing, 2nd ed., ch. 5)") test with two verifies where the data provider should be a [stub](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62 "Reasons to use stubs (The Art of Unit Testing, 3rd ed., ch. 3)"). On [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)") he covers project conventions, a [NerdDinner](https://osherove.com/blog/2009/3/20/test-review-1-nerddinner.html "Test Review #1 - NerdDinner (osherove.com)") test with an unexplained 6, and a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") membership provider whose secret input protocol belongs in public constants. ## Transcript 4,622 words [\[00:10\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=10s) אוקיי, אנחנו עוברים עכשיו דיברנו קודם על היכולת לפתוח בטestטים, עכשיו נדבר על מטבabity של טestטים והרעיון הוא שטestטים הם צריכים להיות להחזיק מעמד הרבה זמן בעצם אחד הדברים הכי מבעסים בטסטים זה שהם הם מרגישים לפעמים כמו בטון מסביב לקוד שלנו ואז אנחנו מנסים לשנות משהו ואיזה טסט צועק עלינו אז אז עכשיו אנחנו נדבר על איך לעשות איך למזר את הנזק הזה ואחת הדרכים הכי בסיסיות זה לוודא שהיוט of work שלנו הוא באמת מתחיל באיזשהו משהו שהוא אטריפ point אמיתי משהו שמשתמש בדרך כלל מתחיל אותו והוא נגמר בend resultלט אמיתי [\[00:46\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=46s) Resultלט זה להחזיר valtion לשנות state של המערכת ככה שההתנהגות של המערכת משתנת לא הסטייט הפנימי לא אכפת לנו מטמי התנהגות משתנת וקריאה לרד פארטי אם אנחנו בודחים כל דבר אחר בתוך המערכת אז בעצם אנחנו יוצרים דבר שנקרא over specification over specificקation זה בעצם מודל הפיקסה שאני הסברתי עליו פעם קודמת שבו אכפת לי יותר מאיך דברים נעשו מאשר האם בסוף אני מקבל את התוצאה הנכונה עכשיו יש המון המון פחד [\[01:19\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=79s) ב בעצם בלבוא ולהגיד לא אכפת לי איך דברים נעשו העיקר שקיבלתי את הוצא צעה הנכונה כי ברמה מסוימת זה יכול כביכול לא להפסיק לדרוש מאיתנו את האפשרות להכיר איך הקוד שלנו עובד מבפנים את ההתנהגות שלו הפנימית אבל זה לא בהכרח נכון כי זה שהטestטים שלנו באמת קיימים ואומרים לנו שהתוצאות הסופיות הן נכונות זה לא מונע מאיתנו את היכולת ללמוד את הסכיל להכיר את הקוד להכיר את הארכיטקטורה שלו זה פשוט סקיל נפרד [\[01:57\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=117s) זה משהו שצריך ללמוד מוד לעשות כמו שעושים רב אפשר גם לוודא שידיעה ארכיטקטונית ושל פאטרנ ושל איך הקוד באמת בנוי ולמה הוא עובד כמו שהוא עובד זה משהו שלומדים אבל הטestטים הם לא משהו שאמור להשפיע על זה פשוט משהו שאמור לתת למו פידבק יותר מהיר לגבי אם יש איזשהו חור ברשת לפעמים להבין למה החור הזה קורה זה משהו שמצריך ידיעה מאוד מאוד עמוכה של [\[02:27\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=147s) ולכן הIT of work שלנו צריך להיות באמת באמת לוודא שכל מה שבפנים מבחינת הוIT test שלנו הוא קופסה שחורה לא לבדוק את האפלמנש יש מקרים שבהם אין ברירה בעיקר בלגסי קוד יש לנו מעט מאוד ברירות של האם לשנות את הקוד או לא ואז אנחנו נכנסים לדברים שניכנס אליהם היום שבהם כן צריך לבדוק קריאות לפרד partטties אפילו שהם לעשות בצורה פנימית או לעשות [פייקים](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") לדברים אה למרות שכביכול הקוד לIT שלנו הוא לא אמור להיות אכפת מה אנחנו ניכנס לזה [\[03:01\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=181s) מבחינת maabity אנחנו תמיד עושים איזשהם הלפר מד ליצירה של אובייקטים לקונפיגורציה של אובייקטים אם עד עכשיו עשיתם מכל תחשבו שמחר יש לי שניים שלושה טestטים שבודקים את קלקטור באיזשהו סט נגיד יש לי פיצ'ר שאומר שקלקטור שישתמשו בו יותר משלוש פעמים אי אפשר להשתמש בו יותר בגלל שזה סוג שלטרי verion אז יש לי חמישה טestטים שם משתמשים בקלטור שכבר קראו לו שלוש פעמים והם בודקים שלושה אנרט שנכתב משהו ללוג שזה עושה נוטיפיקציה עלי סרביס כדי לשלוח לינסקי [\[03:36\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=216s) ושזה מראה איזשהו מסג' למשתמש לכל השלושה האלה לא הייתי כל פעם עושה שלוש קריות לקוליטור בכל אחד מהטestטים אלא הייתי עושה איזשהוט invalid או to invalid או trial state ושם הייתי אומר יש לי שלוש קריות לקוטר שלי והסיבה היא שברגע שמשהו שהוא מוגדר כפיצ'ר פיצ'ר היוםטל מוגדר כשלוש קריאות מחר הפיצ'ר שלטל מוגדר כ-15 קריאות אז אני משנה את זה רק במקום אחד [\[04:08\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=248s) במs test או איפה שאין test cases אז פונקציה של verifיפי שיש בה משהו שעושה זאת אומרתct method לסרטים מבחינת maabity אחד הדברים הכי בעייתיים זה כשטestטים תלויים אחד בשני הרבה פעמים זה לא בכוונה בכוונה זה דבר אחד ונורא קשה כשזה בכוונה שהמשתמש של הטestטים יבין שמשהו קשור אחד לשני [\[04:38\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=278s) אין דרך רציפה וברורה לעשות את הדברים האלה מלבד קומנטים הרבה פעמים קומנטים לא עובדים מהר מאוד הם נהיים ישנים ואף אחד לא מסתכל עליהם או שהם משקרים לך ואתה חושב שהם נכונים ולכן טestטים מבחינתנו הם תמיד אסולטד הם תמיד לא קשורים אחד לשני מבחינתכם כאילו כל טestט שכתבתם הוא חי בעולם משלו הוא מאתכל את המידע שהוא צריך והוא הורס את המידע שהוא יצר אחד הדברים שאני רואה אנשים עושים זה שהם קוראים לטestט מטestט אחר ישירות אחת הסיבות שעושים את זה זה כדי לחסוך את הלוגיקה שעושה איתר [\[05:15\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=315s) אז במקום זה פשוט עושים אסטרctוד לחלק של הrange וקוראים לו בשני הטestטים זה נשמע פה commonסנס אבל זה מאוד פשוט לאנשים ליפול לבור הזה ולכן בtest reviews צריך לבדוק את הדברים האלה מאוד מאוד לעומק. זאת אומרת צריך להיות לכם יכולת להריץ את כל הטestטים בכל סדר כלשהו. אני אגיד לכם עכשיו בבירור, כל הטestו כולל MSTest מלבד במאוד מסוים לא מבטיחים לכם מה יהיה הסדר שבו הטestטים ירוזים. היום הם מריצות את זה בסדר מסוים מחר הפלמנטשטל יכול להשתנות אתם לא יכולים לסמוך על הסדר שבו טסים רצית [\[05:50\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=350s) אחרת צריסה חדשה ואם יר אותו בסדר קצת אחר בגלל אופטימיזציה למי אכפת זה דווקא דבר טוב זה אומר שאם אנחנו לא יכולים לסמוך על זה אנחנו לא יכולים לסמוך שמשהו כבר קרה דרך אגב עוד אחת סיבה שבנטגרration tests הסדר מאוד משנה הרבה פעמים אנחנו מצפים שמשהו יהיה בדataבי שנוכל לעשות delate וכולי אבל גם באינטגרש test הנושא שאפשר להריץ כל test בכל סדר הוא מאוד חשוב בגלל שהמיט שלהם הוא הרבה יותר מסוכך. [\[06:24\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=384s) נחזור חזרה לנו של multiטפל assרוצהity אז אני רוצה שתהיה לי את היכולת לראות כל תוצאה שנכשלה בנפרד. אז אם יש לי multפile as על test על אותו אובייקט אין לי שום בעיה אבל mtפle as על אובייקט אחד על אובייקט אחר שני ריזלטים אחרים מבחינתי אז אני אפריד אותם לטestטים שונים כמובן שגם זאת בעיה [\[06:55\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=415s) זה גם mvc אני אסביר מה קורה פה כל הדבר שאתם רואים פה שנגמר במערך הזה זה בעצם מערך של anonymous objects. כל אחד מהמס יש לו שני properties. Parameter ששימו לב לכולם אותו פרamמטר וtion שהוא בעצם delגate שמפעיל overload של פונקציה שנקראת link. כל אחד מהדלגט האלה מפעיל אload נפרד בעצם פונקציה אחרת שללינק. בסדר? אז יש לנו את המערך הזה [\[07:28\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=448s) ואז יש לנו פה לולאה שעוברת על כל אחד מהמערכים האלה ו עושה expect argument exception nempy זאת אומרת אין זה כתוב ב-MSTest אז אין הסם כתבו help משלהם שאלה האם הם מצפים שהargument exception הוא naly או שהם מקבלים argument exception of nty [\[08:05\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=485s) אז מה הבעיה פה מה רוצים >> פה כמה דבילי הוא קצת בעיה בהתחלה למרות שכמובן אחרי שלקח לי רבע שעה להעביר את הטסט הזה אמרתי וואו מבחינת engineרנג הטest הזה מאוד יפה כי אנג'יניר אני רואה את הטסט אני אומר כן הייתי מגיע לזה באיזשהו שלב אבל מה הבעיה הרידבityי גם גם קשה מאוד להבין את זה בהתחלה גם למישהו שיודע את את כל הסינטקס וכולי. רוב אנשים עדיין לא מכירים על object כמו שצריך גם ככה, אבל יש פה בעיה יותר חשובה. [\[08:38\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=518s) הלולאה הזאת בעצם עוברת על כל אחד מהדברים האלה ובעצם קוראת לכל אחת מהאוברלדים ומצפה לgument exception. הוא לא argument יותר נכון. Argument בסדר? אז מה הבעיה? כמה שרים >> אני בודק פה מטפלס אם מחר האוברלוד הזה נכשל אז כל האוברלודים האלה בכלל לא נבדקים בסדר זה אומר מבחינתי ברגע שזה אוברלודים כל אחד מהם הוא פונקציה נפרדת [\[09:10\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=550s) בסדר למה זה חשוב כי הרבה פעמים אברלד פנש משתמשות בקון קור ולפעמים לא זה אומר שיכול להיות שאכפת לי ויכול להיות שלא אכפת לי מאחרים אם אחד נחשב לפעמים אני אני אתקן פה את הבג ואז אני אראה שגם זה נכשל למרות שתיקנתי את הבג ואז אני לא יודע אם זה נכשל בגלל שתיקנתי את הבג או בגלל שתיקנתי את הבג במקום הלא נכון וככה אני יכול להמשיך אני לא אדע מה קורה ואז נכנסים לדבר מאוד מעניין שנקרא comment run עושים commentמנט לזה ורואים מה קורה עושים comמנט לזה ורואים מה קורה עושים comנט לזה בעצם עושים את אותו דבר שהייתם עושים אם היה לכם מטפל testס רואים מה קורה לכל אחד מהאוברלודים כדי לקבל תמונה יותר טובה של מה באמת קורה במערכת. [\[09:56\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=596s) מלכתחילה, אם היה לי טest לכל אוברו של הפונקציה, צריך להיות טס לכל אווד של הפונקציה, אז הייתי יודע בדיוק שמתוך 15 אוברלודים שלושה לא עובדים וכל השר כן עובדים או 15 אוברלודים לא עובדים. בהתאם לזה יכול להיות שאני מסתכל בבק במקום אחר לגמרי. אוקיי? ולכן הבעיה הזאת שיש לי פה mטיפל as באותו test ואז אני מחביא מעצמי מידע שאלות [\[10:31\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=631s) סתם מחשב שלי יש דרך לעשות משהו שמייצר טestטים אוטומטית בעצם את עשית הפרדה בין הנדס פונקציה אחת >> יש פרויקט ניסיוני שנקרא אפילו פקס מייצר טestטים אבל הוא מחפש משהו שאוטומטית מפריד זה לזה טestטים נכון >> כן >> יפה אז יש איזשהו פרויקט ניסיוני ש לא זוכר את הסו אבל לדעתי הוא נקרא one per test זאת אומרת הראשי תיבות o [\[11:02\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=662s) והרעיון הוא שהוא מסתכל על כל דבר אבל הוא לא הוא לא יכול לעבוד עם הוא רואה multטפle asest ובעצם הוא מסתכל על זה והוא הופך את זה למטפל test לtest percers אוקיי >> אוקיי אוקיי ואז עם הסרט אחד נכשל אתה רואה את האחרים וזה לא יעבוד על דבר כזה >> כן במקרה >> אוקיי שיטה אחרת כאילו לגמרי שיצר >> לא לא אין היום פתרו >> זה נראה לי לפתור ש >> נכון נכון שזה מעניין ששימו לב שאחת הסיבות היחידות שיש לי בעיה עם מטיפל זה בגלל שזה מחביא מידע לא בגלל שזה רעיון כזה גרוע זה יכול להיות אולי לברוא ברדביליטי אבל אפשר לעשות את זה לא חשוב הבעיה הכי גדולה זה שאם הסרט של זורק אקספtion ככה זה בכל הטestי [\[11:46\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=706s) אוקיי אם היה test שלא זורק אפש בהכרח זה >> אלא רק את הceptפtion בסוף הטest להוסף את הפtion >> אז הבעיה הזאת הייתה נפטרת >> הבעיה לאסוף את זה בתוך הטest עושה לך test בלתי קרי והאינפסטקט שראית צריך לכתוב לו טסים משלך וכבר ראית כותב טסט אז תכתוב כבר טסטי שלך תהיה פורסם תכתוב על זה חשוב זה דרך טובה מאוד לעשות כסף אני מבטיח לך >> איך לכתוב את זה כאילו כמו הסרט שפשוט כן מה שהוא כותב לך בסופו של דבר זה כל מה שרץ במשגיע זה משהו שהוא מאוד פשוט כתיבה >> יוטילטי כמו אסרט >> כאילו אבל שבסופו של דבר הוא נותן לך הסרט אחרון שזה יצליח או לא הצליח ובתוק אומר לך משה [\[12:29\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=749s) >> כביכול זה נראה פשוט הבעיה היא לדעת מתי נגמר טסט ואתה צריך חוקים לתוך הטסטוק וכאלה כל זה לא כזה מסוג גם הגיידליינס שאתה בעצם מעביר ובעצם זה יהפכו אני חושב את אחד הכוחות בונטestי שמאפשר לך לעשות קודי על החשיבה אתה תבטל אותו למה כי יהיה לך פתאום מגה יוניט testים שבודקים הרבה דברים ואז יהיה לך מאוד קשה לעשות תהליך נכון שמייצר רגע דווקא לא הייתי מבטל את זה כי זה היה גורם לי להפסיק לחשוב או משהו תשימו לב זה אותו זה אותו ויכוח שיש לאנשים נגד טייפורק אה אם תוכל לעשות מוק לסטטיק אז זה ייח אותך אז תוכל לעשות איזה דיזיין שאתה רוצה אתה לא צריך לחשוב על הדיזיין שלך זה לא נכון הכלים זה לא מה שהם אפשר לעשות משהו טוב בורה >> לא התהליך >> החושיבה החשיבה והקוד רוw והטest רוw ולכן אני אומר וואלה אם היה לי כזה דבר לא בטוח שלא הייתי משתמש בו הפרקes [\[13:22\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=802s) >> אז מה ההגבלה למורכבות של [unit test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") אז היה לך unit testabity maabity וט כל מה שיש לי את השלושה האלה וואלה אין לי שום בעיה >> השלושה הלה יכולים להיות גם עם מולטיפלי זה לא הסטר זה מספיר מד >> אם אפשר היה לעשות את הכליגרש test וזה היה רק מסתיק לפני הייתי עושה הכל כאנטגרש test זה היה פשוט תן לך בשנתיים האחרונות שאני יורד בעולם הרובי ורובי הרבה יותר נפוץ לעשות test מאשר unit test פשוט by default רוב הטestטים שאתה מריץ נגיד נגד rובי ril הם testים שמשתמשים בדataביס [\[13:53\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=833s) אז מלכתחילה כל הIT testים ברובי הםation tests אז הם לוקחים יותר זמן אבל זה הדפולט אז התחלתי לכתוב הרבה acceptance test עםספק ולהריץ את האתר דרך הדברים האלה וראיתי וואלה אפשר היום להריץ headless כולל ג'ס כולל הכל את כל הטestטים את כל הקוד לבדוק בינגרation testcancest שהם דווקא מאוד קריים אם הייתי יכול לבדוק רק את הפיצ'רים של הדבר הזה unit testing זה לא כזה לא הייתי לא הייתי ננע מזה אבל יש עם זה כרגע בעיות המהירות שאני מקבל את הפיטק היא מאוד איתית וזה לכן יש תנועה שלמה של אנשים בעולם הרו שבה ואומרת זה לא מספיק טוב שאנחנו בעיקר עושים testing בואו נתחיל לדבר על unit testing להפריד מהדפיס דברים שבעולם הדנט אנחנו מדברים עליהם כבר יחסית הרבה זמן בעולם הרובי רק בשנה שנתיים האחרונות אנשים מתחילים לדבר עליהם למרות שזה תרבות שיש בה המון המון ניסיון בטestינג, רוב הניסיון בכלל בא מעולם האנטגרשט testing. [\[14:48\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=888s) זה נורא מעניין. אז כביכול הכאבים שאנחנו פה כביכול פותרים הם כאבים גם שם ושם בדיבולט באים עולם ש אומרים וואלה אני יכול לעשות הכל ככה זה לא כזה נורא ואנשים חיים זה כבר שנים וזה לא כזה נורא אבל אז ניסיתי ניסיתי לעשות אפליקציה שבה אני עושה רק אינטגרש עשיתי דווקא וואלה הייתי דווקא די רוצה מהדבר הזה הבעיה היא שלקח לי שעה וחצי כל פעם לדעת אם שברתי משהו זאת הבעיה ושם היוטינג נכנס אז אם הייתי יכול לפתור את הבעיה הזאת שגם אינטגרשט testing היו לוקחים לוחים מה אני לא דתי לגבי הדברים האלה אם הייתי יכול לעשות מטיפל בלי בלי לשבור משהו אז אני בטוח שהייתי מוצא מקרים שבא עם מלטפלסט זה לא כזה דבר [\[15:29\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=929s) זה שוואלה צריך לעשות קודר ולהגיד יש דברים שאתה לא יכול לעשות או דברים שאל תעשה אל תעשה סי שר אפשר לכתוב קוד נוראי אפשר לכתוב קוד נחמד זה לא אומר שהשפה צריכה להשתנות כדי לאפשר קוד נוראי זה אומר שצריך לעשות קודם דבר חשוב עבודה עם אנשים אני לא זוכר מה הייתה השאלה, אבל אתם צודקים, זה מה שחשוב כן מטיפל אסרט לא רעיון טוב כרגע [\[16:01\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=961s) הנה דוגמה יותר מעניינת כמובן נעשה לכם זום הנה דוגמה לטest שימו לב זה טסט שכביכול אמור לא רוצה במטיפל גם אפילו בואו נתחיל מהשם מישהו רוצה לקרוא את השם לא מספיק [\[16:37\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=997s) מה לא הבנתי execute with a syringer action compete suc ‏suf זה מאוד sucess מה אנשים אומרים מתכוונים כשהם אומרים compete successfully >> לא נזרק אפtion זה בדרך כלל מה שהם מתכוונים עוסקים איתך אז הייתי משנה את זה לדes not ווואלה הייתי שם פה את הנדרסורם כי יותר קל לי לקרוא אבל עוד פעם אנדרסקורים זה איזשהו סטייל שבהתחלה נורא עוזר אבל רוב האנשים לא כותבים אדרסקורים הם [\[17:09\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1029s) לא בגלל שזה לא דבר דבר טוב אל בגלל שרוב האנשים לא מבינים כמה שזה דבר נחמד כשיש את האנדרסקורים האלה את השניים האלה ואז הם כותבים טestטים כאלה ואף אחד לא יכול לקרוא הם יכולים לקרוא אותם אבל אם הם לא דוברי אנגלית נייטיב שעוברים את השיניים אוקיי אז מה היה מה הבעיה בטest הזה מה הבעיה שאני מנסה להראות היא בכלל פה למטה זה משתמש במוק [Moq](https://osherove.com/blog/2012/6/27/the-future-of-isolation-frameworks-and-how-moq-isnt-it-for-n.html "The future of Isolation frameworks, and how Moq isn't it (for now) (osherove.com)") ואני רואה פה שני verifיפי זאת אומרת מלכתחילה יש פה בעיה זה בכלל לא משנה מה הטest הזה בודק שני verifיפי אם אתם זוכרים verify זה אומר שיש לי obק אז יש לי פה שני obקט ובtest אמור להיות לי בדרך כלל מוק object [\[17:53\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1073s) למה זה בעיה שיש לי שני מobקט בטest בודק שתי דברים >> מה אתה בודק שתי דברים אני בודק שני דברים ומה הבעיה עם זה מחשב שניה >> כן זה מלטפל מבחינתנו זה מטיפל אסרט זה על שני אובייקטים שונים אם הוריפיי הזה נכשל הוריפיי הזה זה לעולם לא יעבור אבל יש פה בעיה יותר מעניינת האם בכלל אני צריך פה שני objects למה יש פה שני מobטs אני מסתכל על השמות שלהם ואני אומר וואלה רוב הסיכויים שאחד מהם בכלל לא צריך להיות מט temד data provיידר [\[18:25\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1105s) Data provיידר רק מהשם שלו אני מבין שכל מה שהדבר הזה אמור לעשות זה לתת מידע לתוך האפליקציה שלי ובדרך כלל ההבדל בין מוקים [לסטאבים](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1 "Introducing stubs (The Art of Unit Testing, 2nd ed., ch. 3)") זה הפow הכיוון שבו האינפורמש זורם סטאבים נותנים ים מידע לתוך האפליקציה ומק objects בודקים מידע שיוצא מתוך האפליקציה החוצה דata prviידר בדרך כלל אומר לי תדמה איזשהו מידע לתוך האפליקציה עכשיו מהידע הקודם שלי אני יודע שבדרך כלל [\[18:57\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1137s) אנשים שכתבו שהתחילו לכתוב טestטים לפני יותר משנתיים הם רגילים למוד אחר של עבודה עם אוקצ רגילים לתרבות שבה אתה עושה וריפיי לכל דבר שאתה יכול לעשות לו וריפיי בגלל שאתה יכול לא בגלל שזה רעיון טוב זה בגלל שככה לימדו אותם בגלל שככה גם לימדו אותי מ לימד אותי אפילו לא זוכר זה פשוט היה איך איפה שהוא בתרבות אני זוכר שנכנסתי והתחלתי לכתוב את הטסטים הראשונים שהיה להם objects וראיתי בד verify all expectations בד בכלל לא קשור לשום test היה לי מג שמותח בסטאפ לא היה קשור לשום test וכל הטestטים שהשתמשו בו גם היה להםיפי אחי זאת אומרת by defaultט בידתי את כל הדברים ולא ידעתי אם זה דבר טוב או לא היום אני יודע שזה דבר מאוד בעייתי מבחינת המטנבity [\[19:48\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1188s) אז בינתן שתי הידיעות האלה אני אומר הוא על רוב הסיכויים שהדבר הזה בכלל לא צריך להיות פה והסיבה היחידה שזה פה זה בגלל שיהיה איזשהיא קונבנציה בגלל שלא יודעים שזה יכול לפגוע במטנabity של הטest אם הייתי יכול להסתכל על השם של הטest ולהבין מה הected behavour אז הייתי גם יכול להגיד איזה מה הוא בטוח צריך להיות גם הבעיה היא שפה הect ב הוא שהוא שום דבר לא זור exception אין פה שום expected behav שאומר שמשהו צריך להתרב [\[20:19\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1219s) אז יכול להיות שבכלל שני הוריפיים שלי לא בסדר אולי אני לא צריך פה בכלל שום מקצט או אני צריך אחד test אחד עם obקט וטest אחד שבודק שאין אספtion יכול להיות שזה שני resultס שבינותן איזשהו אפtion שנזרק אז זה בולע אותו ואיזשהו טestט אחר שאומר וגם תבדוק שזה נקרא יכול להיות שצריכה להיות פה הפרדה אבל השם של הטestט הרבה פעמים עוזר לי להחליט מה הייתה אמורה להיות הנריזל המקורית [\[20:51\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1251s) תשימו לב גם שלכל דבר פה קוראים מוק למרות שהרבה פעמים חלק מהדברים הם סטב מוקטם tata provider expectect במקום mq הישן זה הסetאפ החדש זאת אומרת קריאה ‏low temp data ותחזיר new dictiontionary של string ותשימו לב verifiable verifiable verifiable זוכרים את verifiable evil זכאני עושה verify [\[21:23\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1283s) אני בודק גם שהפונקציה הזאת נקראת וגם שהפונקציה הזאת נקראת ותשימו לב atm זה משהו שיכול להיות מאוד מסוכן save temp data אמור להיקרה מקסימום פעם אחת. עכשיו בדרך כלל לא הייתי בודק דבר כזה. הסיבה היחידה שהייתי בודק אם מה שהוא נקרא רק פעם אחת זה אם זה באג לקרוא לזה יותר מפעם אחת. [\[21:54\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1314s) בדרך כלל זה לא כזה באג לקרוא למשהו יותר מפעם אחת. זה יכול להיות בעיות של פרפורמנס. ואז אולי הייתי בודק את הדבר הזה. אבל בדרך כלל לא הייתי מתחיל עם טסט שבודק כמה פעמים מה שהוא נקרא. הייתי בודק שהוא נקרא בכלל. ואחרי זה אולי הייתי עושה לזה אופטימיזציה. הסיבה היא שלפעמים אנחנו בודקים כמה פעמים מה שהוא נקרא בes exactly three times ולא באמת אכפת לנו. מחר אנחנו עושים אופטימיזציה וזה נקרא רק פעמיים במקום שלוש פעמים. הכל עדיין עובד אבל הטest שלנו נכשל. [\[22:25\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1345s) האנדריז הוא עדיין אותו דבר. אז אני לא רוצה להכריח את הקוד שלי את הקוד שלי לעבוד בצורה מסוימת אם אני לא חייב. אוקיי? ולכן יש פה המון דברים שהייתי יושב עם הבן אדם הייתי אומר האם באמת צריך פה את המוקט הזה? האם הדבר הזה הוא לא בכלל סטב הייתי עושה לונame והוא מוציא את הוריפי מפה האם זה צריך להיות שני testים אחד שאתה קורא לזה ואין אספtion ונתן exceptפtion [\[22:56\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1376s) ואחד לא בואו נראה מבחינת הסטרינ זה בסדר כי ווליו אין שום בעיה אין פה עוד איזהשהו משהו ממש ממש גרוע אז הייתי משנה את השם של הטestט הזה הייתי בודק באמת כמה מקוםסר צריך כמה סטבים באמת יש פה ומה expectected behav באמת שאלות >> אם יש לך test כזה שרק רוצה לבדוק שלא נזרק עם אפtion אז יכול גם בעיקרון לא לעשות בכלל כי פשוט אפש [\[23:30\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1410s) יש לי does not thr אם אני באמת רוצה לעשות את זה >> בכל מקרה גם האפש >> מסכים איתך אני בכלל לא משתמש באסט אני פשוט כותב בשם של הטtion בסדר ואז אין לי שוםט אבל השם של הטסט אומר לי למה אין לי שום אסרט ואז אני עושה רביו ואני מבין עוד שאלות אוקיי זה מבחינת [maintainability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec2 "Writing maintainable tests (The Art of Unit Testing, 2nd ed., ch. 8)") בואו נדבר על [readability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec3 "Writing readable tests (The Art of Unit Testing, 2nd ed., ch. 8)") structure solution שהוא קריסution [\[24:01\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1441s) שבו אתה יכול למצוא כל דבר ואת הדברים שמתאימים לו אז קודם כל יכול להיות שיש לכם איזשהו convention איזשהו פולדר שתחתו תחתף שמים את כל הטestטים כל הtest proקטס מתחילים במילה test או נגמרים במילה טסט אבל יש איזשהו קונבנציה זה חשוב מאוד גם בגלל הסדר וגם בגלל שמישהו שנכנס יש לו איזה מישהו שנכנס לצוות יש לו איך להמשיך הוא לא צריך לנחש את הדרך שלו אוקיי דרך אגב אנשים שנכנסים לצוות שכבר כותב בTD הרבה יותר קל להם להתחיל לכתוב בTD בגלל שבדרך הם נכנסים [\[24:38\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1478s) הם מתאימים את עצמם לארגון שאליו הם נכנסים אנשים שנכנסים לארגון שבו יש קונ שהכל מתחיל בA אז הכל אצלם יתחיל בA מאותו רגע. זה לא שיש איזשהו משהו שצריך ללמד, זה פשוט הדרך שבה עושים דברים. ולכן אם אני רוצה לכתוב טestטים ואוטומטית יש לי במקום שבו אני יודע שהטestטים של הדבר הזה נכנסתים לטestטים של הדבר הזה אז כמעט לא צריכות להיות לי שאלות. זה ממש convention overciguration. יש לי קונבנציות והרבה פעמים זה מחליף קונפיגורציות. [\[25:16\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1516s) ועוד פעם אני מחפש פה תשימו לב זה לוity שזה פרט toen source של מיקרוסופט שימו לב שאין לי פה את המילה integraation tests אבל בדרך כלל אני יכול לנחש interception configuration רוב הסיכויים שזה שם יש לי כל מיני configuration files וכולי הייתי משנה את השם הזה שם של הtest לפחות אבל אין לי פה את ההפרדה בין unity inration test מה שאומר שרוב הסיכויים שיש לי פה מיקס אם הייתי מריץ את כל הטestטים ושניים היו נכשלים. צריך לבדוק טוב מאוד אם השניים האלה זהרation test או לא. ואם כן הייתי שם אותם בפרויקט נפרד כדי לוודא את זה. [\[25:47\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1547s) ואם לא הייתי שם את זה בפרויקט של unit test. אבל זה היה לוקח לי זמן ולכן מלכתחילה שיהיה לי כבר את ההפרדה הזאת שאני לא אצטרך לעשות את זה בעצמי. שמות הנה פרויקט זה אם אני לא טועה בנרדנר יש טestט כזה מה אתם אומרים מה הייתם משנים פה >> שם >> שם אוקיי למה הייתם משנים את השם [\[26:19\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1579s) >> מה אני יודע שאתה בודק את זה אבל מה אמור לקרות זה מה שנקרא what the fuck test. אוקיי, הסיבה שזה what theפק test בגלל שלא רק שהשם גרוע, העשרט בכלל לא קשור לשום דבר. שש >> שש. מאיפה שש הגיע? לא שש. >> שש זה חשוב אולי זה לא חשוב? >> לא רואים את זה ב >> איך ידעת שזה יהיה שש? [\[26:52\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1612s) זוכרים שבטestטים אני אמרתי לכם אף פעם אל תעשו בסטאבים שלכם דברים שהם הרדקודד זה מה שקורה ואז פתאום אתם תסתכלו בשאר הטסטים ותראו שש חוזר על עצמו להרבה טestטים אז אתה מתחיל לחפש שש הנה שש איפהשהו יש איזשהו סטאר [\[27:27\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1647s) איזה אחד כזה מתחבה ושם מינימום פספ הוא שש אחלה מצוין כל מי שקורא את הטestי מסתכל על ששום לא יודע מאיפה זה רוב האנשים לא תומכים לחפש מאיפה זה הגיע אין איזשהו קנס שמשתמשים בו אפילו בטestי ולכן מגיק number מובילים הרבה פעמים לזה שהמספר מתרבה כי אף אחד לא יודע מאיפה הוא מגיע אבל כולם יודעים שהוא חשוב אוקיי ולכן הנושא הזה של הידן values הוא לא פחות חשוב מאשר הנימין של הטest [\[27:58\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1678s) במקרה הזה דרך אגב הטestט הזה נוצר בחטא בגלל שהבן אדם זאת אומרת זה טסט קלאסי שבן אדם שלומד [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") והוא יושב עם מישהו והמישהו הזה לימד אותו את את העיקרון הכי בסיסי של TDD וזה תתחיל מטest שנכשל אז הוא התחיל מטסט שנכשל הוא לא התקמפל בהתחלה הוא קרא לcונטרולר registerסטר הוא עשה resultלט והוא לא חשב על שם טוב נעשה גט כי אני צריך לעשות אני צריך לבנות את הרגסטרם לזה לעבור אבל על מה אני אעשה [\[28:31\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1711s) על מה אני אעשה לבדוק שרג'יסטר באמת עובד שאני מקבל משהו לא חשבו על שום דבר אומר אה בוא נבדוק בוא נבדוק את הפסורד אז תח את הפסורד אז פתחו את הפסורד במקום זה אפשר לבדוק שהVW resultלט שקיבלת זה רגסטרw זל אפשר לבדוק שזה לפחות is not אבל הדברים הכי בסיסיים פה בעצם הם אומרים קיבלת את הדברים שאני שטלתי ככה שאני יודע שבאמת השתמשת באובייקטים שלי אז לפחות פה הייתי עושה פה איזשהו consס שאומר [\[29:02\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1742s) [Fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") viwד data מינימוםפורד לנפס או משהו בסגנון הזה כדי שהייתי יודע מאיפה השש הזה מגיע עוד דברים חשובים אם כבר מדברים על דברים שהם הרדקורד ד או לוגיקה הנה הדבר הזה אני קורא לו hן prוקocוקol hen prוקocוקol אומר שאיפהשהו בטestינג באינפסטרקט יש לך איזשהו פרוטוקול שאם היית יודע אותו הייתי יכול לקבל המון המון ערך ממנו פה אתה רוצה ליצור user במership של ASP.NET [\[29:36\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1776s) אז אז בעיקרון בfake mership provider אם אתה שולח לו usernר name שסuse לפורד שהוא goodפס והאמייל הוא אימייל אז אתה תקבל שהממברשיפ הצליח אתה צריך לדעת את זה זה לא נמצא בשום מקום אבל בוא נניח שאתה רוצה לדמות שהממברשיפ לא הצליח זה פשוט מאוד [\[30:08\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1808s) ותעשה לו נקפס ובאינם תשלח את המברשיפסטוס שאתה רוצה. זאת אומרת תשים בסטרינ של האימייל את הממברשיפ סטטוס שהיית רוצה שהוא יופזר לך. אוקיי? מי יודע על זה? אולי הבן אדם שכתב על זה וגם הוא בטח כבר שכח. אוקיי? אז יש איזשהיא סיסמה סודית שאם אתה משתמש בה בטestטים אתה יכול לדמות סטטוסים. עכשיו תדמיינו את הקורה של הטestט שמסתכל על טס ואומר למה אתה מייצר אותו עם האימייל הזה לאזזה לשמור [\[30:43\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1843s) תחשבו שהוא מייצר יוזר והוא אומר זה אותו עם יוזר אחר לא ממברשיפ לא הצליח אז אף פעם לא לעשות את הדברים האלה בלי איזשהו פרוטוקול שהוא public constני יכול להתייחס אליו מבחוץ אם eסם נקודה fake membersh provider נקפת good image להוציא את הדברים האלה לקנס כדי שבטest שלי אני אראה מאיפה הסטרימים האלה מגיעים [\[31:20\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1880s) עוד דברים שקורים הרבה שכל דבר קוראים לו מוק אבל מה שאני מבקש זה שכשמייצרים דברים שיורשים מדברים אחרים תקראו להם פיק כי הרבה פעמים אתם לא יודעים איך תשתמשו בהם אז זה מוק princiפle אבל בעצם הייתי קורא לזה fake principleפle לגביing לא נדבר יותר מדי עוד דבר שהייתי עושה זה הייתי מפריד את הארט מהact זה דבר מאוד חשוב בגלל שאחרת הסרט שלי יכול להיות מאוד מאוד ארוך ואני מעדיף שהוא יהיה יופרד לשתי שורות ואז אני יכול גם לעשות דברים עם המסג או לדוגמה אקספש או דברים כאלה [\[31:57\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1917s) עוד דבר חשוב דרך אגב שלא דיברתי עליו עכשיו שאני חושב על זה מה באמת קורה פה שימו לב יש לי איזשהו פייקס prinפל וכשאני רוצהityי אני מחזיר fake identity יש פה בעצם ניסיון לעשות בעצם שרשרת של אובייקטים שהם פייק בסדר עכשיו מה יקרה לפייק אidentityי יש פרטי שהוא גם אובייקט צריך להצריך גם ממנו איזשהו פייקט [\[32:30\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1950s) היום אם אנחנו משתמשים בפריורקים החדשים כולל tyמוס ומק גם לדעתי [FakeItEasy](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html "FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition? (osherove.com)") וסבסט הם עושים מה שנקרא recury face אז בעינתן שאפשר לעשות over או משהוטי אוטלי או פנקציה וירטואלית היא מחזירה משהו שהוא לא value אלאקט אז האובייקט הזה by defaultט יהיה fake לא צריך להגיד לו שזה יחזיר אז אם אני אעשה fake substitute for substitute for i principle נקודה identiity [\[33:04\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=1984s) כבר יהיה fake והidentity נקודה משהו שאובי גם יהיה fake וזה חשוב מאוד כי מבחינת המטבity של הטestים לאחר כך הטestטים שלי יהיו הרבה יותר קצרים וגם אם אני מוסיף propפר פונקציות הטestסטים פשוט יעבדו אני לא אצטריך להגיד להם כל פעם להוסיף עוד פייקים ועוד פייקים אז היום הדבר הזה זה בדרך כלל אומר לי וואלה תשתמש באיזשהו פריימורק אל תעשה את זה ידיים [\[33:39\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=2019s) כן בעניין הזה יש דרך לדעת אם מה שאתה מקבל כאן זה משהו שהוא פייק או לא פייק מבחוץ כי נגיד אני לא יכול להפוך בעצם כל אובייקט לאובייקטים כי יש גם כאלה שאין טעם לעשות את זה אז השאלה אם מי שקורא את הטest יכול לדעת אם מדובר באובייקט פייק או לא באובייקט פייק אה אתה מדובר בראנטיים לבדוק אם משהו פייק אז כבר הטך מסובף מדי >> לא לא ברמת רנטיים ברמת כתיבה אני מסתכל על קוד ואני רוצה לדעת אם הדבר הזה הרי הוא אינטרפי אדנטity >> אבל אתה רואה את הטest הטest אמור להיות ברור מספיק שאת תתע מה פייק ומה לא פיק אם זה מהשם של המשתנה או מכל דבר אחר [\[34:14\]](https://www.youtube.com/watch?v=0JEOcZyVw-c&t=2054s) אם אתה לא יכול אז משהוז תעשה את זה שזה שזה יהיה ברור יקרים בסדר עוד שאלות לגבי input values גם readability אז שימו לב אני אוהב input value שהם לא אותו דבר גם בגלל שלפעמים החדר משנה אבל גם בגלל שאני אוהב שאני רואה איזשהו פאטרן אנחנו מתוכנתים לזהות פאטרנים גם בעיניים שלנו ואני אוהב במיוחד ## Related - [Avoid overspecification](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8) · The Art of Unit Testing, 3rd ed., ch. 8 Book section on avoiding overspecification, the lesson's term for checking how things are done instead of end results. - [Verifying the wrong things](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-5) · The Art of Unit Testing, 3rd ed., ch. 5 Verifying the wrong things, as in the Moq test with two verifies where the data provider should be a stub. - [Multiple mocks, asserts, and hidden results](https://osherove.com/blog/2011/2/9/multiple-mocks-asserts-and-hidden-results.html) · osherove.com Roy on multiple mocks and asserts hiding results, the problem with the two-verify and looping tests reviewed. - [Writing maintainable tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec2) · The Art of Unit Testing, 2nd ed., ch. 8 Writing maintainable tests in C#, covering the isolation and overspecification issues reviewed in this lesson. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Entry points and exit points](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18), ch. 1 - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19), ch. 1 - [Reasons to use stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_62), ch. 3 - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 #### The Art of Unit Testing, 2nd ed. - [Current isolation frameworks for .NET](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec5), ch. 5 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Introducing stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec1), ch. 3 - [Writing readable tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec3), ch. 8 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 #### osherove.com - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) - [Over Specification in Tests](https://osherove.com/blog/2008/7/12/over-specification-in-tests.html) - [Test Review #2 – ASP.NET MVC Unit Tests](https://osherove.com/blog/2009/3/21/test-review-2-aspnet-mvc-unit-tests.html) - [Test Review #1 - NerdDinner](https://osherove.com/blog/2009/3/20/test-review-1-nerddinner.html) - [The future of Isolation frameworks, and how Moq isn't it (for now)](https://osherove.com/blog/2012/6/27/the-future-of-isolation-frameworks-and-how-moq-isnt-it-for-n.html) - [FakeItEasy or NSubstitute? Which should I use for samples in art of unit testing 2nd edition?](https://osherove.com/blog/2012/6/26/fakeiteasy-or-nsubstitute-which-should-i-use-for-samples-in.html) [Previous lesson Best Practices Continued](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/best-practices-continued/) [Next lesson Readability Practices](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/readability-practices/) --- title: "Readability Practices" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/readability-practices.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/readability-practices/" tags: [] author: "Roy Osherove" description: "Lesson 19 of 22 in TDD in .NET in Hebrew (Day 3 - Unit Testing Practices), 1:23. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Readability Practices 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 3 - Unit Testing Practices Lesson 19 of 22 Duration: 1:23 [Watch on YouTube](https://www.youtube.com/watch?v=QvHaaU5xaoA) Spoken in Hebrew ## In this lesson Roy Osherove recommends ordering tests so that each one changes only one thing in the inputs compared with the test before it, such as one more character in a string, which makes the pattern readable and shows how the feature was built step by step. He sums up his [three pillars](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8 "The pillars of good unit tests (The Art of Unit Testing, 2nd ed., ch. 8)"), tests that are easy to read, easy to maintain and [trustworthy](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7 "Trustworthy tests (The Art of Unit Testing, 3rd ed., ch. 7)"), and calls [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") almost the only way he knows to see tests both fail and pass, though [bugs in tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11 "How can we know we don’t have bugs in our tests? (The Art of Unit Testing, 3rd ed., ch. 11)") can still mislead. ## Transcript 191 words [\[00:02\]](https://www.youtube.com/watch?v=QvHaaU5xaoA&t=2s) לראות טestטים ואני אומר הטestט הזה בא אחרי הטest הזה. כל מה שמשתנה בין הטestט הזה לטסט שמתחתיו זה דבר אחד בלבד. אם משתנים שני דברים באינפוטים, לדוגמה גם האורך וגם פרפרטי אחר, לדוגמה שהוא גם invalid, אז זה הרבה יותר קשה להבין את זה מאשר שיש לי סטרינ ועכשיו ההבדל הוא שהוא בקרקטר אחד יותר. אני רואה פטרה ואני רואה את המהלך הדרגתי שבו אני בודק כל חלק של פיצ'ר. מבחינתity זה מאוד מאוד עוזר עם הטestינג טובים ככה לפעמים אני ממש יכול לעשות טריקבק ולראות את הדרך שבא הפיצ'ר נכתב [\[00:37\]](https://www.youtube.com/watch?v=QvHaaU5xaoA&t=37s) נורא נורא מעניין להסתכל על זה ככה זה גם מאוד קרי אלה בעצם שלושת העמודי התוך מבחינתי של טestינג שקל לקרוא אותם קל לעשות להם מטנס ואני סומך עליהם עכשיו ttd היום זאת הדרך כמעט היחידה שאני יודע כדי באמת לוודא שאני סומך על הטestטים שלי כדי לראה אותם גם במצב של קיש שלו וגם במצב של הצלחה. אמ אבל לפעמים אפילו זה יכול לשקר לי אם יש לי באגים בטestטים וכולי. [\[01:08\]](https://www.youtube.com/watch?v=QvHaaU5xaoA&t=68s) אז גם צריך מאוד להיזהר מהנושא הזה של פאס. בוא נעשה הפסקה של רבע שעה ואחרי זה ניכנס ללגסיקות. כן יש שאלות רבע שעה סק >> רגע ## Related - [Writing readable tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8#ch08lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 8 Writing readable tests, the pillar this lesson extends with ordering tests one input change at a time. - [RTM ready tests](https://osherove.com/blog/2009/12/31/rtm-ready-tests.html) · osherove.com A short way to describe tests that are readable, maintainable and trustworthy, the three pillars summed up here. - [Testing the test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-2) · The Art of Unit Testing, 3rd ed., ch. 2 Testing the test: seeing it fail as well as pass, which the lesson says TDD gives you. - [A buggy test gives a false failure](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_137) · The Art of Unit Testing, 3rd ed., ch. 7 A buggy test gives a false failure, the lesson's warning that bugs in tests can still mislead. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Trustworthy tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7), ch. 7 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [How can we know we don’t have bugs in our tests?](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-11), ch. 11 #### The Art of Unit Testing, 2nd ed. - [The pillars of good unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-8), ch. 8 [Previous lesson Maintainability Practices](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/maintainability-practices/) [Next lesson Legacy BlogEngine Project Overview](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/legacy-blogengine-project-overview/) --- title: "Legacy BlogEngine Project Overview" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/legacy-blogengine-project-overview.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/legacy-blogengine-project-overview/" tags: [] author: "Roy Osherove" description: "Lesson 20 of 22 in TDD in .NET in Hebrew (Day 3 - Legacy Code), 8:02. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Legacy BlogEngine Project Overview 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 3 - Legacy Code Lesson 20 of 22 Duration: 8:02 [Watch on YouTube](https://www.youtube.com/watch?v=yS87tH70uvg) Spoken in Hebrew ## In this lesson Roy Osherove introduces the [legacy project](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") for the third day, the BlogEngine.NET blog engine, which has no [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") but has integration and [acceptance tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-10#sigil_toc_id_178 "E2E/UI isolated tests (The Art of Unit Testing, 3rd ed., ch. 10)"). Some are written with WatiN, which is based on Ruby's Watir and works mainly with Internet Explorer, and others in a framework whose tests are written in Razor pages that run in the browser; of 20 tests, five fail. The exercise is to understand why and make all the tests pass, get to know the code and its dependencies, and try writing a new test [before refactoring](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_225 "Writing integration tests before refactoring (The Art of Unit Testing, 3rd ed., ch. 12)"). ## Transcript 916 words [\[00:07\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=7s) BlogEngine.NET הוא מנוע של בלוגים שמאפשר לנו לעשות כל מיני דברים, כולל לכתוב ולוג, קומנטים, טקבק, פינבק וכל מיני דברים מעניינים אחרים. אנחנו הולכים לעשות לכתוב לו טestטים. עכשיו הפרויקט הזה מעניין מכמה בחינות. א' יש בו המון, אין לו בכלל [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1 "Defining unit testing, step by step (The Art of Unit Testing, 2nd ed., ch. 1)"), אבל ב' יש לו כמה integraation test אוceptance test מאוד נחמדים. בעצם אם אני לוקח את הפרויקט אני עושה לו קונטרול F5 כדי להריץ אותו ואז אני עושה קליק ימני run test [\[00:39\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=39s) יש לי פרויקט של testing שמריץ לי את הal את הארט exporer ובעצם מפעיל כל מיני פונקציות בceptance test האcest פה כתובים בכמה frameworים אחד הפרamewורקים שזה כתוב בהם זה אם אתם מכירים זה web application testing in.net אז מרוסס על פרויקט ברובי שנקרא Watir או Watir שזה web application testing in ru [\[01:13\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=73s) הפרw הזה בעיקר מכיר אתנט expפור ו יש פה עוד כמה פיצ'רים נחמדים א' הטestטים וואו כתובים בnitט אז טן in זה סתם פריימורק שמשתמשים בו איך אני אראה לכם את הטestטים פה בעצם הטestטים רצים בזמן שאני מדבר תשימו לב כמה זמן לוקח להם לרוץ אבל יש פה עוד טים בעוד פרימוק שנאק קישות או קיחות קישות שזה פרימוק שנכתב על ידי בחור בשם rקרי עוד איזה altגי [\[01:47\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=107s) שעבר לרובי ואז חזרה לדוטנט ולקח כמה רעיונות משם וממשימש אותם בדוטנט ובין השר מה שהוא מימש זה framewורק שנקרא קוט שזה מאפשר לך לרשום testive ברזור שזה השפת templליטנing של שאפשר לכתוב ב-ASP.NET ‏viw ומאפשרים לך לעשות אסרטים שנראים קצת כמוספקים משהו צריך להראות כמו משהו אחר להריץ את הטestטים כביכול בפרודקשן אפשר להריץ את הטestטים האלה גם בפרודקש אז פה אתם רואים בינתיים הטestטים רצים [\[02:19\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=139s) בודקים את הפינס שאפשר לעלות comמנטים כל מיני דברים כאלה לעשות לogגן אם אני אעשה פה בינתיים view outpט כל הטestטים האלה רצים עם TestDriven.NET זאת אומרת זה כתוב ב-NUnit אתם רואים שהטestטים רצים בינתיים דיברתי ובעברו איזה כמה דקות סך הכל את כמות הטestטים שרצה פה זה 15 טestטים אבל כל טestט מורכב מהרבה דברים הטestטים עצמם [\[02:54\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=174s) יש פה בעצם שני פרויקטים של טestטים למרות שנראה שיש רק אחד הטest הראשון הוא זה והטestטים פה כתובים בnitוס שזה שזה בעצם לוקח את והולך לכל מיני דפים אבל יש גם טestטים שכתובים בכיחוטה שיהיה לכם גם לינק בתרגילים כי זה בעצם אתה כותב את הטestטים אתה יכול לכתוב אותם או בקונסול או ב שנייה בוא נראה איפה זה [\[03:28\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=208s) כן נכון אני אסגור את זה זה לא מתחת לאדמין זה לא מתחת לוין זה מתחת את הטestטים האלה זה בעצם בספרי הטestס כאשר הטestטים כתובים בריזור כל הטestטים של הCHML הם טestטים שבעצם גם הטestטים שלIT של מבקשים מוטין ללכת לדפים האלה ולהריץ את הטestטים שכתובים פה טוב יש פה איזשהי בעיה עם הסנטeקס הייט אבל בגדול זה rיזור כאשר הסנטקס של הטest פה נראה ככה [\[04:01\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=241s) Following שימו לב avatar test ואת השם של האly לא חייבים את השם שלא רוצים ואז יש it should כן it should שזה בעצם המילה שבה משמשים בדרך כלל ואז יש פה איזשהו סטרינ שזה בעצם בא מעולם הרובי שימוש בסטרינג ככה ואז יש לנו בעצם איזשהו למדה כי צריך להחזיר פה איזשהו [\[04:31\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=271s) משתנה מסוגד delegate ופה כתוב ממש test תפתח את הlog settings instance avatar get avatar image return שמשהו true force שזה מתחיל בככה וזה ends with ככה ואז תשימו לב שבסוף יש עוד משהו מאוד מעניין [\[05:09\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=309s) יש כל מיני דברים כמו שבי שימו לב יש פה כל מיני דברים אין שבינ שביטול שזה מאוד דומה לאסטים של [NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3 "First steps with NUnit (The Art of Unit Testing, 2nd ed., ch. 2)") אבל זה בעצם חלק מהפריורק של כיפות n עכשיו הפריורק הזה הוא כולו בסך הכל פייל אחד שבוקחים ושמים בפרויקט כל הפריורק הוא בפייל אחד זאת אומרת הוא מאוד פשוט והוא כבר נמצא בפרויקט שלכם המשימה שלכם כרגע היא לפתוח את ה בוא נראה דרך אגב אם הכל כבר נגמר או לא outpט [\[05:40\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=340s) אוקיי אתם רואים 15 פסחמישה פיל אז יש סך הכל 20 טestטים ויש חמישה שנכשלים עכשיו תחתרו לכם אתם המפתחים אתם באים עושים גטליס מריצים את כל הטestטים חמישה טestטים נכשלים אם אם זה test יכול להיות שזה עניין של קונפיגורציה ודרך אגב יש פה כל מיני עניינים שצריך לסדר המטרה שלכם היא קודם כל לגרום לכל הטestטים פה לעבור כדי שנוכל אחרי זה לעשות ריפקטורים [\[06:10\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=370s) לפרויקט הזה בסדר זאת אומרת להבין למה הם לא עוברים לתקן את הטestינג אם צריך יכול להיות שיש פה כל מיני דברים שעובדים על מערכת מרוחקת ולא עובדים על המערכת הלוקלית להבין מה קורה פה מכיוון שמדובר פה בעיקר בcept ‏test. ברגע שיש לנו בלגסי קוד סדרה של testים שעוטפת את הקוד אפשר להתחיל לעשות משהו עם הקוד הזה. אני יכול להגיד לכם מראש שהטestטים שנכשלים גם קשורים לקיקוטה. צריך להבין מה קורה שם. [\[06:41\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=401s) אפשר גם את הקירות האלה להריץ ישירות מפה. אני יכול ללכת ללוקל הוסט איפה שאני מריף את הפרויקט לכתוב test ופשוט ללכת לאחד הדפים ותשימו לב שאם אני הולך אליהם ישירות אני רואה אותם והם עוברים. אוקיי, ככה אפשר להריץ את כל הטסטים ידנית אפילו בפרודקש. [\[07:12\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=432s) שאתם צריכים להשתמש בו נמצא פה pitl. Labacy legגy doc יש פה האפרק casס משנה אחרת ביטלי לא עובד תשימו לב אז זה פשוט casי סטנדרטי. אז מה שאנחנו נעשה עד ארוחת הצהריים זה את החלק הראשון של הדוקיומנט הזה. בסדר? כתוב לכם שם איפה עוצרים לצהריים. כתבתי במיוחד שלא תעשו יותר מדי חס וחלילה. זה להבין את הפרויקט הזה קצת להיכנס אליו, להכיר את הקוד שלו, להבין את הדפendנenנy שלו, לגרום לכל הטestטים לעבור ואפילו לנסות לכתוב טest חדש, [\[07:42\]](https://www.youtube.com/watch?v=yS87tH70uvg&t=462s) Test חדש עם אחד מהטרימוקים האלה שנמצאים פה. פשוט להתחיל לשחק עם הדבר הזה ולראות איך זה מרגיש להתנסות איתו וגם לראות איך זה מרגיש להיכנס לידי הסיקות שלא כתבתו בסדר שאלות אוקיי בהצלחה פגש פה ‏Yeah. ## Related - [Writing integration tests before refactoring](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10#ch10lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 10 Writing integration tests before refactoring, the role BlogEngine's existing integration and acceptance tests play. - [Where do you start adding tests?](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10#ch10lev1sec1) · The Art of Unit Testing, 2nd ed., ch. 10 Where to start adding tests in legacy code, the first question when approaching an untested project like this one. - [The Testing Feasibility Matrix](https://osherove.com/blog/2005/7/25/the-testing-feasibility-matrix.html) · osherove.com Roy's formula for deciding where to start unit testing legacy code, useful when mapping BlogEngine's dependencies. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [E2E/UI isolated tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-10#sigil_toc_id_178), ch. 10 - [Writing integration tests before refactoring](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_225), ch. 12 #### The Art of Unit Testing, 2nd ed. - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1), ch. 1 - [First steps with NUnit](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-2#ch02lev1sec3), ch. 2 [Previous lesson Readability Practices](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/readability-practices/) [Next lesson Refactoring- Introduce Instance Delegator](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/refactoring-introduce-instance-delegator/) --- title: "Refactoring- Introduce Instance Delegator" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/refactoring-introduce-instance-delegator.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/refactoring-introduce-instance-delegator/" tags: [] author: "Roy Osherove" description: "Lesson 21 of 22 in TDD in .NET in Hebrew (Day 3 - Legacy Code), 17:36. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Refactoring- Introduce Instance Delegator 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 3 - Legacy Code Lesson 21 of 22 Duration: 17:36 [Watch on YouTube](https://www.youtube.com/watch?v=JtNR-j0Tzq0) Spoken in Hebrew ## In this lesson Roy Osherove sets out to test the static Send method of a class named Manager in the ping namespace, which sends a trackback or ping for the links in a post or comment, and suggests finding its dependencies by calling it and seeing where it fails. The calls that send a trackback or ping are the [end results](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)"), and the tests should prove the loop and each if. Because the class is static, he introduces instance delegator: remove static from the class, move the logic into an instance method that the static method calls on a new manager, then [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") settings such as the trackback check in a [testable subclass](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95 "Partial mocks (The Art of Unit Testing, 3rd ed., ch. 4)"). ## Transcript 2,587 words [\[00:04\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=4s) אה לא צילם את המקונסגרו שם את הדלת בסדר רגע סגרו אתכן >> סגירו את הדלת תפעילו את המזגן >> תביא את המסג' >> נראה לי שווה שכולם יעמדו להוריד את הגירה >> אוקיי למי עברו כל הטestטים דרך אגב >> למי עברו למי למי נכשל רק טestט אחד למי נכשלו יותר מטestט אחד אוקיי אוקי מה למדנו עלגרש testing היום ילדים זה שונה את המחשב >> אם זה לא עובר זה בסדר >> אם זה לא עובר אתה רואה כל הזמן אני אומר לך מה היה קורה אם יש יוניטסטים שם מסובחים אז רובו הסיכויים שלא הייתם שמים לב אליהם וזאת אחת הסיבות שצריך להפריד את הדברים האלה אוקיי אנחנו נניח לצורך המשך התרגול של היום כשכל הטestטים עוברים אצלכם על המחשב [\[00:52\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=52s) דרך אגב הרבה מזה קשור לאם רסing כאדמין או לא וחלק מזה קשור גם לגרסאות שלד דוקים שמכונות לכם על המחשב אבל זאת המטרה האמיתית שלנו להמשך היום יש לנו קלאס שנקרא מנג'ר נכון שאנחנו לא שמעתם קלאס עם שם כזה למנגר יש פונקציה publicקס static ש קוראים להסנ זאת הפונקציה שאנחנו הולכים לנסות לכתוב להestטים היום אנחנו בהתחלה נתחיל לכתוב טestטים [\[01:24\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=84s) גם באותו פקטורים לבריאות בלי טיפ והמטרה היא שאתם תראו שיש דרכים כמעט כל חתיכת קוד להפוך אותה לטבabית ולבדוק אותה וזה גם פרפקטורים שחשוב ללמוד קצת אני אסביר מה המטרה של המנג'ר הזה המנג'ר נמצא בתוך נמספס שנקרא פינג והרעיון הוא מישהו יודע מה זה פינג או טרקבק בבלוגים מי יכול להסביר את זה דרך [\[01:55\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=115s) של זה דרך של מחבר פוסט להודיע למחבר פוסט אחר שהוא קישר עליו בוא הסתב לבלוגר אחר בלוגר אוקיי זה קצת כמו מה שכתר אחרי זה נהיה שאתה כותב על מישהו ואטומטית הוא יודע שהזכרת את השם שלו אז בבלוגים אה אתה עושה לינק לבלוג של מישהו אחר ואייכשהו אוטומטית מופיע לו איזה לינק מתחת לבלוג שלו עצמו שאתה כתבת עליו וזה נעשה באמצעות סדרה של שרטים בעולם שנקראים ping server וb servers והמטרה שלהם היא בדיוק לעגור את המידע הזה על בלוגים שמקשרים אחד לשני ותרך זה לעשות שיחה קצת יותר מעניינת בין בלוגרים [\[02:38\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=158s) אז הפונקציה הזאת היא בעצם פונקציה שמקבלת publishable שזה יכול להיות פוסט או comment כל דבר שיכולים להיות בו לינקים למשהו ובהתאם אם יש טרקבק URL או URLים לבלוגים אחרים היא שולחת אוטקבק אופינ בהתאם לכל מיני תנאים מסוימים. אבל אנחנו הולכים לנסות לבדוק את הפונקציה הזאת בהתאם לדף שכבר יש לכם פתוח אצלכם בבראוזר. אבל הבעיה האמיתית היא שיש פה המון צרות שלותסטביליות. [\[03:09\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=189s) F12 לדוגמה יש לנו block settings. Trackb שזה קשור לקונפיגורציה אז זה סוג של dependency שמאוד קל לזהות. אבל הרבה פעמים יש depend בקוד מג שאין לנו מושג מה הdependencies שלו ואז עושים דבר שאני קורא לו wishfulation וזה סתם מילה יפה ללנסות להריץ ולראות מה יקרה אז בטestטים שלנו אנחנו יכולים לנסות להפעיל את הפונקציה ולראות מה קורה אם מקבלים איזשהו אפtion מסתכלים על הסט ורואים איפה דברים מתחילים להיכשל ושם כנראה הדepפendנסי נמצא ואז מנסים לחשוב באיזה רמה כדאי לנו לעשות [פייק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") למשהו הזה או לעשות לעשות סטאר או לעשות או שצריך מוקט פה כדי [\[03:58\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=238s) לבדוק את הקומפוננטה שלנו. אז אחד הדברים שאני ממליץ לכם כשאתם מתחילים לכתוב לבדוק את הפונקציה הזאת זה פשוט לנסות לקרוא לה ולראות מה קורה רגע אבל תר לי מה שאתה אומר כי את עצ אומר אני לא אני לא יודע בכלל מה אני בודק לא אני לא יודע מה הדפנסי של מה שאני זה אותו דבר אבל >> לא בכב זה אותו דבר הרבה פעמים הקוד לגסי שלך מסתמך על קוד שלא אתה כתבת מסתמך על אינפסטקטור שלא אתה כתבת >> אוקי >> ולכן אתה לא יודע מה הדפנenנies שלו למה אני מסתכל על הקוד ואני אובל את הדברים כי אני לא רוצה לבדוק אותם לא אתה לא צריך לבדוק אותם המטרה שלך היא למצוא את הUNIT World ולבודד אותו שקט שליטה עליו זה כל המטרה זאת אומרת אתה רוצה לבדוק עד כמה אתה יכול להריץ את הדבר הזה בזיכרון בלי לפנות אתדabסיט בלי לפנות פיילסיסטם שזה ירוץ בלי רדינ אז בהתחלה אתה לא יודע איפה הגבול הזה עובר בתוך הכל אז אתה צריך לראות מה קורה אבל >> עכשיו בלגסי קוד זה לא tvd חשוב להבין שהכללים של TVD לא חלים פה בכלל לגס קוד וגדול [\[04:59\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=299s) זה לקחת בדבוק וודק כטוב כל אדם לעצמו ופשוט לצאת לשדות ולראות מה קורה עם סוס פשוט לקחת גם רובה טוב כי אתם תראו שם כל מיני דברים ואתם ומה שקורה שם זה נשאר ביניכם לבין לבין הקומפיילר כמובן שאחרי זה מישהו יצטח לקרוא את הטestטים שלכם אז תרשו אותם קריאים כמה שיותר אבל טestטים של לגסיקות יכולים להיות הרבה יותר מסובכים יכולים להיות להם הרבה יותר depפendנenes ובעולם האמיתי בקוד שלא נכתב עם testing אז הוא גם קוד שלא נועד לטestטים בדרך כלל זאת אומרת צריך למצוא המון דרכים יצירתיות לבדוק את הקוד הזה. [\[05:34\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=334s) ובקוד שאתה לא מכיר, כמובן להסתכל בקוד ולהבין את כל החתיכות שלו זה בהחלט חשוב, אבל צריך באיזשהו שלב גם להיות פרודוקטיבי ופשוט לנסות להפעיל אותו. עכשיו, אני יכול לקחת רק את המתודה הזאת ולהפריד אותה מכל הדפנדנenנס ברמת הקס, אבל זה לא בהכרח רעיון טוב. אני הרבה יותר מעדיף שאני משתמשת במשהו להבריאות, שאפשר להריץ גם בזיכרון, אז אני אריץ בא את הדבר הזה. אני מעדיף שזה שלא יהיה אכפת לי מהאימפלמנטיש כמה שיותר. בסדר? ולכן אני רוצה לבדוק עד כמה impפלמנטש אני יכול להשתמש בו בלי לקבל אספtion בלי להפעיל דטבס כדי שהעומק שלי שאני מפעיל את הIT one הוא יורד מבחינתי אפילו שלוש חבות אבל אם זה הכל בזיכרון זה לא כזה מפריע מבחינתי הend resultלט הוא מה שחשוב ואז השאלה את השאלה מה הend resultלט איפה הend resultלטs פה [\[06:21\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=381s) אז יש פה שני סוגים של אד resultלט היא קרה קריאה לtrackbנ וקריה לפי בקסנט אלה שני הנרזלצ היחידים שיכולים להיות פ אוקיי עכשיו מבחינתנו פינbקס וצקבק נסנ הם יכולים להיות thדפ party נבדוק שמישהו קרא לטרקבק נקס כי אם באמת נבדוק שהם קרו זה כבר יהיה אטגרש test לכל דבר בסדר עכשיו זה לא אומר שלא צריך test זה אומר שמבחינתנו האינטגרש test הם יהיו מטבח משלים לדבר הזה אני רוצה לבדוק ביניטest שקראתי לדבר הזה ולבדוק ביניטest שקראתי לדבר הזה אם אני לא קראתי לדבר הזה על זה בעצם הדברים הגדולים שאני אכוון אליהם. [\[07:04\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=424s) עכשיו, במסמך שיש אצלכם במחשב כתוב מה תרצו לבדוק. לדוגמה, אם אני שולח שני UR בקונטנט של IUBL, אם אני שולח שני URLים אז אני באמת עובר על כל אחד. אני רוצה להוכיח שיש סיבה שהלולאה הזאת נמצאת שם. לולאה זה כשיש לך יותר מאחד אז אין לי צורך לבדוק עם שלושה. אני יכול לבדוק עם שניים שהובר בלולה ושולח את כל אחד מהם לטראקב. אני רוצה להוכיח שיש סיבה לאיף הזה ולאיף הזה. אז אני אבדוק כל אחד מהם אני רוצה להוכיח שאם בטק back הוא דווקא מחזירפס אז הוא לא שולח לט [\[07:39\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=459s) אוקיי עכשיו הסיבה היא יכול להיות שגיליתי בג ולפעמים זה כן קורה לפעמים זה לא קורה אז אני רוצה לבדוק אותו בכל התנאים האלה עכשיו כל מבחינת הדיזיין יש פה דברים מבחינתity שעוד לא עברנו עליהם לדוגמה כל הפונקציה הזאתי סטטית והיא בקלאס שהוא סטטיק זאת אומרת לדוגמה פה יש לי trackb send בעולם יותר פשוט הייתי אומר וואלה תביא לי איזה אינטרפי של i trck i trackb ותבלוג שckb נקרא ואתם באמת יכולים לעשות את הדבר הזה [\[08:15\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=495s) הבעיה היא לאן אתם מים את האינטרפס אין פה שום אינס של קס שמקבל אינטרפס כל הקלאס הזה הוא סטטי וכל המתודות פה הם סטט אופליקסטיק אוטסטיק בסדר אני מניח שאצלכם זה לא ככה אל תניבתי ואם אני מנסה לבדוק את הדבר הזה ואני רוצה להשתלט על הbקס send אני לא יכול לשלוח אינטרפס אני גם לא יכול לעשות פה אstract and over בגלל שאני לא יכול לעשות over לקסט אני לא יכול לרשת ממנו כי אין לי אינסטנס של משהו אז אני עוד פעם בבעיה אז שום שום דרך מהרפאקטורים שלמדנו עד עכשיו לא יכול לעזור לנו אז מה שנלמד עכשיו זה דרך ריפאקטורינג שיכולה להביא אותנו לרפ פקטורים שאנחנו יכולים לעשות. [\[09:00\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=540s) זאת אומרת אם אין לנו instance אנחנו נעשה פה שיתן לנו instance והרפקטורing שאני ללמד פה נקרא introduce instance delegator זה אומר שאנחנו נעשה נהפוך את הקריאות של פונקציה סטטית לקריאה לפונקציה שהיא איסטנס בגדול מה שזה אומר זה ככה אם הקלאס הזה שלי הוא סטטי אוקיי כל הקלאס הזה הוא סטטי אני רוצה שתהיה לי את היכולת להפוך את הקלאס הזה לקס אסטי חלק מהרפקטורing אני הולך להוריד את המילה סטטיק מהקלאס מי יודע מה המילה סטטיק בעצם נותנת לנו ברמת הקסה [\[09:37\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=577s) שכל המת >> שכל הס מה מה זה מונע מאיתנו לעשות >> זה מונע לעשות ניו וזה מונע מאיתנו לכתוב מתודות של אינס כל המתודות בקס חייבות להיות סטט מבחינת השימוש של כל הקלאסים האחרים בקס הזה זה לא משנה שום דבר ריפה גדול זה בסך הכל מוריד חלק מהקונסטרינטים של הקפיילר עלינו אוקיי זה שם מוריד את הקלאס סטטי לא משנה התנהגות בסך הכל עושה את הקלאס יותר מגיש לאינסטנסים ברגע שהורדתי את הטat instance אני יכול לעשות [\[10:10\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=610s) את הדבר הבא אם אני רוצה שתהיה לי גישה אם אני רוצה שתהיה לי דרך לעשות אסטרct וadדוס interfס אני צריך שתהיה לי דרך אני צריך שהמתוד send תהיה על אינסנט של משהו אבל המתוד הסנ היא כרגע סטית אז מה שאני אעשה זה בעצם להכפיל את המתודה הזאת. אוקיי? [\[10:40\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=640s) ובעצם מה שאני הולך לעשות זה ככה. אני הופך להפוך את המתודה הסתית של למתודה שלא עושה שום דבר מלבד לעשות new instance של manager וקורת לסנ על הance. אוקיי? זאת אומרת לקחתי את כל הפונקציה שלס sנ אני לוקח את הפונקציה הישנה של שהייתה סטטיק ואני מוריד את הסטטיק ממנה ומשנה לה את השם כי אחרת הקפיילר צל אני קורא לזה sendal אוקיי היא לא השתנתה מבחינת הפלמנטש בשום דבר עדיין רק עכשיו המתודה הסטטית אני לא רוצה לשנות את ה את העובדה שהיא שם מכיוון שיש לי את כל הפרודקש קוד שעדיין משתמש במתודה הסטטית המטרה שלי היא לא לשנות את ההתנהגות של כל מי שקורא לי אלא לשאר את התנגות פנימית ולכן מה שאני עושה פה זה [\[11:26\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=686s) Maner sendal עם הפרמטרים שלי אוקיי אז מה שהיא עושה עכשיו היא בסך הכל עושה דלגציה לאיance ולכן זה נקרא instance delegator אז הפונקציה שהייתה פעם סטטית לא עושה שום דבר מאשר new manager נקודה sendal internal היא עכשיו מטה שנמצאת על instance של clס ואם יש לה אינסט שלס אנחנו צים לעשות את כל הרפקטורים שעשינו קודם זאת אומרת אני יכול עכשיו להגיד וואלה block settings instant enable trend [\[11:58\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=718s) זה dependency אז אני יכול לקחת את כל הדבר הזה לעשות extract method ולהגיד get enable trackb send להפוך אותו ללאסטatטי לעשות אותו וירטואלי ואחרי זה לעשות לו overיט בעצם לרשת מהמנגר לעשות testable manגס משלי לעשות שם להחזיר שם מה שאני רוצה עכשיו יש לי את היכולת לעשות את הרפקטורים הזה כי זה באינסטנס אז אם קודם היה לי רק סטטי לקחתי את הסטטי ואמרתי [\[12:28\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=748s) אתה אתה כביכול עושה מה שעשית קודם ההבדל היחיד הוא שאתה עושה את זה על אינסטנ של קס עכשיו פה אני עושה ניו אבל מ בעולם האמיתי מה שבדרך כלל הייתי עושה הייתי לוקח את הניו מנגר ו עושה לזה אקסטר זה מתודה שהיא כנראה get man שלא בהכרח תמיד עושה ני אבל זה כבר זה כבר לא בעיה זה כבר משהו שעושים בלי קשר מה שחשוב זה לדעת לעשות את הדליגציה הזאת בגלל שבמקרים כאלה לא תהיה לכם הרבה ברירה כדי שתוכלו לבדוק משהו שהטestטים יהיו קריאים הרבה פעמים זה שיטה מאוד מאוד פשוטה ונוחה [\[13:03\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=783s) שלא משנה את ההתנהגות היא אך ורק משנה את הטסטביליות של הקלאס שאלות לגבי מה שראיתם עד עכשיו כן מי רוצה שאני אחזור על מה שעשיתי >> לא יהיה יותר קל כאילו לא יהיה יותר קל פשוט בפ לתפוס את הקריאה סטא >> בטח שזה יותר קל אבל אני רוצה שתלמדו את שתי השיטות בגלל שלא תמיד יהיה לכם כלים ולא תמיד זה רעיון טוב להשתמש בכלי בשביל לתפוס את זה לפעמים כן ולפעמים לא >> באיזה מקרים לא היית אומרים >> במקרים שבהם הטestט יהיה בלתי קרי בעליל בגלל כמות הדpנenנies [\[13:41\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=821s) וגם בגלל ש' חשוב לכם ללמוד את הטכניקה של הרפקטורי חלק מהקורס אתם תגלו שלפעמים זה הרבה יותר פשוט מאשר לכתוב טest ולגלות את כל האינטרספtionס אבל לפעמים זה באמת יותר קל להשתמש בטל מה שחשוב זה שתהיה לכם אופציה שלא תהיו תגידו אני חייב לעשות את זה ככה אלא אני בוחר לעשות את זה ככה זה הכוח האמיתי בסדר >> ואז הוד הקוד עכשיו נהיה קצת לא קריכ >> הקוד נהיה לא קרי >> של הפרודקש כי עכשיו אתה קורא לפונקציה >> כן אני יכול לעשות את זה >> בעיקרון יש לך עכשיו >> כן >> אה אפשר לעשות את זה [\[14:19\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=859s) אוקיי בסדר בסדר? דרך אגב, לא בטוח שהייתי עושה את זה אנטרנל, הייתי עושה את זה פאבליק בגלל שמה שהייתי רוצה זה שקוד חדש כבר ישתמש באינסטנס ולא ישתמש בסטטיק. המטרה שלי להיפטר מהסטטיק הזה בסוף. לאט לאט אני אני אפטר מכל הטיפנסי שמשתמשים בסטאטיק עד שיום אחד אני לא אשח את הסטטיק בכלל. >> אבל עם האינטרנט אתה יכול לקרוא לזה אינטרנל? אני יכול לקרוא לזה מתוך האסמלי. אני יכול לעשות את זה אבל פאבליק ולא אינטרנל. >> אבל אתה רוצה לקרוא בטest? אתה רוצה לקרוא לפונקציה? >> בטסטים שלי אני יכול לעשות internal שהטestטים שלי יוכלו לראות את זה עם האטריבט. [\[14:50\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=890s) אבל בדרך כלל מה שהייתי עושה הייתי משאיר זהפליק בגלל שמבחינתי זה פחות משנה הייתי יכול אם זה באמת מפריע לי הייתי עושה את זה publicקל ואז עושה internal וזה בלטו בטestים שלי אני לא מפעיל את הטat method אני עושה new manager או testable manager וקורה לס internal אוקיי דרך sendal זה סתם שם שאני בחרתי תם תקו לזה send instance או תמצאו לזה שם אחר שאתם יותר אוהבים השם פחות משנה כל זמן שזה שם שונה מסנ >> אולי עדיף אה עוד אופציה זה במקום לעשות את הריפאקטור הזה פשוט להפוך משהו שהסתטי [\[15:25\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=925s) קלאס לסינגלטון ואז פשוט אין לך את הדפליק שלי סינגלטון זה משהו שמחייב אינסטנס כן >> ולכן זה זה בהחלט אבולוציה שיכולה להביל אותך לסינגלטון >> גם כאן אתה זה יהיה מי >> כן אז יהיה לך אתה יכול להגיד ככה instance כן >> הבעיה עם סינגלטון זה שאתה עוד פעם צריך להחליף אותו איכשהו בטestטים שלך נכון אה אה אבל אתה עדיין יכול לעשות את את אותו תדליק בעצם יכול לעשות בטestים שלך ניו מנג'ר אבל בדרך כלל בסינגלטון הם מחביעים את הקונסטרקטור כדי שאף אחד לא יוכל לעשות את זה הסינגלטון בדרך כלל הוא גם משהו שהוא לא testable יותר מדי אבל אתה יכול כמו שעשינו בטיים אתה יכול להגיד [\[16:04\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=964s) Instance נקס set לטesting אבל אתה עדיין צריך את הצד הזה כדי שיהיה לך אינסטנס מלכתחילה תחשבו על זה כאזשהו צד איזשהו מתאטפ כדי שבכלל תוכלו לעשות משהו על זה סינגלטון הוא גם אופציה אתה יכול גם בסינגלט שהקונסטרקטור יהיהד ואז מי שיורש ממך יעלה לו את רמת הביity לפליק >> נכון נכון אבל עוד פעם זה כבר תלוי באיך אתם רוצים שהדיזיין שלכם יראה זה לא קלאס על דיזיין זה פשוט להראות לכם איזה אופציות יש מפה ההחלטה איך הדיזיין יראה הוא כבר שלכם בסדר אני לא רוצה להיכנס לזה כי זה יכול דיון של יום בפני עצמו מה כדאי וגם יש לכם פה כל מיני איזשהו סטנדרטים שאולי אתם רוצים לשמור עליהם זה חשוב [\[16:43\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=1003s) גם הרבה פעמים זה מפחיד אנשים לחסוף משהו ‏V שאנשים יכולים לרשת ממנו בלי שהם יתכוונו רק בשביל הטest. אבל זה הכל עניין של דיון שהוא לא רלוונטי לנו כרגע כי אנחנו לומדים טכניקה. הדיון המוסרי של מתי להשתמש בטכניקה זה באמת דיון לקורס אחר. אוקיי? שאלות? מישהו רוצה שאני אראה עוד פעם את הטכניקה של איסון אליגטור? אוקיי, אז מה שאני מבקש, [\[17:14\]](https://www.youtube.com/watch?v=JtNR-j0Tzq0&t=1034s) נלך להמשיך את הצעדים. אתם לא צריכים עכשיו להוסיף לעשות את התרגיל הראשון של להוסיף test. מבחינתי תתחילו מהתרגיל השני, מיד אחרי התרגיל של הטestי. מה שכתוב אטר launch מבחינתנו, אחרי האדום הזה אנחנו ממשיכים משם והמטרה היא לסיים את כל הדטה ה בסדר? בהצלחה. ‏Ja. ## Related - [Issues in breaking dependencies for unit testing](https://osherove.com/blog/2005/8/23/issues-in-breaking-dependencies-for-unit-testing.html) · osherove.com Roy on breaking multiple dependencies in an existing class or method, the situation with the static ping Manager. - [Refactoring your design to be more testable](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec4) · The Art of Unit Testing, 2nd ed., ch. 3 Refactoring your design to be more testable, the kind of change instance delegator makes to a static class. - [Testing Complex Logic with TDD](https://www.youtube.com/watch?v=PP8UDXt268M) · YouTube Shows the test-specific subclass (extract and override) technique in .NET, used here to override the trackback setting. - [Tips for Testable code and for testing legacy code](https://osherove.com/blog/2007/6/10/tips-for-testable-code-and-for-testing-legacy-code.html) · osherove.com Tips from consulting on testing a hard-to-test business logic method, close to the trackback sending code. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19), ch. 1 - [Partial mocks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95), ch. 4 #### The Art of Unit Testing, 2nd ed. - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 [Previous lesson Legacy BlogEngine Project Overview](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/legacy-blogengine-project-overview/) [Next lesson Summary and Discussion Day 3](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/summary-and-discussion-day-3/) --- title: "Summary and Discussion Day 3" url: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/summary-and-discussion-day-3.md" canonical: "https://courses.osherove.com/courses/tdd-in-net-in-hebrew/summary-and-discussion-day-3/" tags: [] author: "Roy Osherove" description: "Lesson 22 of 22 in TDD in .NET in Hebrew (Day 3 - Legacy Code), 18:48. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Summary and Discussion Day 3 1. [Courses](https://courses.osherove.com/#courses) 2. [TDD in .NET in Hebrew](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) 3. Day 3 - Legacy Code Lesson 22 of 22 Duration: 18:48 [Watch on YouTube](https://www.youtube.com/watch?v=8JAPnkm18-A) Spoken in Hebrew ## In this lesson Roy Osherove explains that a [fixture setup](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_171 "Setting up and tearing down (The Art of Unit Testing, 3rd ed., ch. 9)") runs once before all tests and usually means something slow is initialized, and agrees that the [refactorings](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") made the code [more testable, not better designed](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec3 "Pros and cons of designing for testability (The Art of Unit Testing, 2nd ed., ch. 11)"). On whether to [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") the method that parses the links out of the content, he prefers to keep as much code in the [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") as stays fast, in memory and readable, fakes threads, processes and the file system, and calls the choice [the art of unit testing](https://www.manning.com/books/the-art-of-unit-testing-third-edition "The Art of Unit Testing, Third Edition (The Art of Unit Testing, 3rd ed.)"); a debate on [testing private methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_160 "Avoid testing private or protected methods (The Art of Unit Testing, 3rd ed., ch. 8)") follows. Each pair then writes two or three tests for real production code that go into source control. ## Transcript 2,872 words [\[00:01\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=1s) בDSM שמתם לב שיש בסטestי יש פה אבט שנקרא testure setup וtest feure setup זה אטריוט שקורה פעם אחת לפני כל לפני כל הטestטים זאת אומרת גם אם יש לכם 10ה טestטים הפונקציה הזאת תרוץ רק פעם אחת קס בMS זה נקרא קס לדעתי אבל יש גם פונקציה setטאפ בחלק מהקלאסים שיורשים ממנה שהיא קוראת פעם אחת לפני כל טest משתמשים ב כדי להתחיל את כל הטestטים [\[00:34\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=34s) אז בדרך כלל אם אתם תרא תראו testפק setup זה אומר כמעט בטוח שיש לכם בידיים כי מאתחילים משהו שלוקח הרבה זמן להתחל אם זה היה קורה לפני כל טest אז משתמשים בזה פעם אחת לפני כל הטestטים לדוגמה להרים סביבה כלשהיא לנקות משהו לסגור את כל האינטרנט אקספלוררים או מה שזה לא יהיה אוקיי איך המרגש לגבי הטסם שכתבתם עד עכשיו הרגשות טענות איזה שהם אינסייטס מעניינים [\[01:08\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=68s) אה שור >> קיאור אוקוד המקורי >> קיאור הקוד המקורי שהיה יפה קודם פתאום נהיה מכוער אוקיי >> נהיה פחות קר >> הוא נהיה פחות קר אוקיי בסדר הריפקטורים של הוא רק עושה אותו יותר testable הוא לא עושה אותו יותר דזי תשים לב תשימו לב זאת אומרת לכן ההבדל ביןסטב לדין מאוד גדול בסדר עדיין יכול מאוד מכוער ומאוד טסable אוקיי זה אינסט חשוב מה עוד היה משהו >> היה אצלנו בחדר ששמנו לב ש [\[01:41\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=101s) חלק מהאנשים קראו לה פונקציה כשהם נתנו קונטנפט מסומלץ כאילו ממש סטרינג שמכיל תוכן עם לינקים >> ואומרים ואני בחרנו דווקא להתעלם מזה כאילו לעשות שם [פייק](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") לחלק הזה ולהחזיר ממש כזה פשוט את התוצאה שממש מחילה כבר URLים מפורסרים והיה שם איזשהו דיון כזה שבעצם הבנו שזה לא שחור ולבן אין פה תשובה בהכרח 100% טובה לתת את הURLים כסטרינגים אומר שאתה בודק יותר פיסות קוד כי אתה נכנס ליותר חלקים [\[02:15\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=135s) ואני אישית מרגיש שזה מוריד קצת מהקריאות אנשים חיים חושבים שזה מוסיף לקריאות לשים את הלינקים בטestטים אז זה קצת עניין של טעם אבל מה שלי היה חשוב העיקר שם אני חושב זה לדעת לבחור במודע אם אתה מכניס או מוציא את הפיסה כזאת מהסקופ של הטסט שלך כאילו לדעת שאתה מסוגל להוציא את זה או להשאיר את זה ולדעת מה במה אתה בוחר ולמה אוקיי אז אני אסביר בגדול הוא דיבר על הגest from content [\[02:46\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=166s) היכולת לעשות פרסing בעצם get your content משתמש בגular expression כדי לעשות פס לכל הURים בקונטנט אז היו כאלה שבחור פשוט לתת content שמכיל את הURLים היו כאלה שבחו לעשות [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") לגט ופשוט להחזיר מה שהם רוצים ואז לא צריך לכתובנט נורא מסובך שמכיל את הURLים בפנים. שתי הדרכים הם בסדר. דרך אחת כוללת יותר אפלמנטש בתוך היוט ודרך אחת כוללת פחות. זאת אומרת אם אתם בוחרים לשלוח item נק שכבר מכיל את הURL אז בעצם אתם אומרים get your from content הוא חלק מהtest שלי. [\[03:22\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=202s) אם הוא אם הוא לא עובד אז הטest שלי לא עובד. אבל זה גם אומר שהייטם content האינפוט שלי נהיה הרבה יותר מסובך אז יש מקרים שבהם באמת הייתי עושה פיק לגנ ויש מקרים שלא בדפולט אם אני יכול וזה לא עולה לי ברידביליות או במטנביליות או שלא זה לא מכשנה לכתוב את הטסט יותר מדי אני מעדיף לכלול כמה שיותר דברים בטסט שלי לא להוריד זאת אומרת אני מעדיף שהיוניט of work שלי יהיה כמה שיותר מנופח ויכיל כמה שיותר קוד בצפנים כל הזמן שזה רץ בזיכרון רץ מהר יש לשיטה על כל הדברים readable mable [\[03:57\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=237s) והסיבה היא שבאמת הדבר הזה הוא נכלל בינט אבור הסיבה היחידה שלי לעשות לזה פייק זה אם נורא קשה לעשות את האינפוט הזה או נורא בלתי קרי הטest שיוצא מזה ואז באמת הייתי עושה לזה פייק כי זה מבחינתי נהיה depפendנency depפendנency זה משהו שאין לי שליטה עליו או שנורא קשה לייצר משהו שיעמוד בסטנדרטים שלי תארו לכם לייצר משהו שהוא out of memory exception זה גם אפט שנורא קשה לייצר אז עושים לו פייק זה סוג של depפendנסing [\[04:28\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=268s) שתי הדרכים הם בסדר היו כאלה שהצליחו לעשות את הדרך שבה הם לא עושים פיק לגט והטest עדיין מאוד קרי בגלל שהשתמשו בים מאוד פשוטים סידרו את הקוד בצורה פשוטה ובויזואלית הפרידו דברים יפה עם ספייסים הויזואלית של הקוד מאוד חשובה בדברים האלה ואם אתם יכולים לגרום לזה לקרות עם משהו בפנים אז תעשו את אפילו הייתי אומר וואלה אולי אני אפילו יכול לעשות משהו עם remמוט פייל כל זמן שזה משהו לוקי על הדבר הזה ואפילו לקרוא לזהרש test אם אני לא צריך לעשות לזה אקסטרctט וואלה אני אולי אני לא אעשה לזה אקסטר [\[05:05\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=305s) אני לא דתי בנושא שחייבים לכתוב [unit test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") אם הטest עדיין ירוץ מהר והוא יהיה אטגרש test אז מה אף אחד לא עומד מזה אלא אם כן הטest הוא למחשב יחוי זהגרש ואז מישהו יכול לק >> אבל כן >> הבעיה הייתה מבחינתי בזה שכבע בURL הייתה מכשילה את כל הטestטים בבת אחת כולם עכשיו כל הטestטים תלויים בHRF למרות שיש הרבה לוגיקה מעבר טוב אז ולכן זה זה משהו שנתון לשיקול אם אתם רואים שוואלה האינפוט הזה מסובך וגם האינפוט הזה צריך להשתנות כל הזמן כי הדרישות לאיך URL נראה משתנות כל הזמן אז זה משהו שהוא תן לזה [\[05:47\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=347s) בסדר אין פה תשובה אחת בגלל זה אני קורא לזה [The Art of Unit Testing](https://www.manning.com/books/the-art-of-unit-testing-third-edition "The Art of Unit Testing, Third Edition (The Art of Unit Testing, 3rd ed.)") שזה זה החוכמה היא למצוא את השביל הדג שמחבר בין משהו שהוא readable ומטable לפי מה שאתה אומר וואלה אם אני כולל את זה זה לא בכלל מטable כי מחר אני משנה משהו ופתאום אני צריך לשנות את הרגול אקפרש ובום שברתי מלא test >> אבל לא לא תעדיף פונקציה שתתמקד רק בזה כשאתה רוצה לבדוק את זה ושהשאר ידלגו על החלק הזה אם יכולות >> יכול להיות שאני אבחר שאני אגיד זה depפendנency ואז יהיה לי test במיוחד לג אבל יש יש לי בעיה עם get your content [\[06:26\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=386s) הוא private method private method ב implementation detail מחר get content לאח regular expression מחר הוא הסתמך על איזה webסרס שעושה ומקבל את זה מface.com איכשהו מאיזשהי צריך שוב כל הטestטים יפלו בגלל שהם ימשו את זה עם זה הם פתאום יהיו איתיים מאוד ואז אני אעשה לזה פלמנטשטל עד אותו רגע לא שינה לי אז לא השתמשתי בו זה פישט להתס ברב אם זה מסבך לי את הטest כשאני צריך לעשות פייק למשהו הטסט הקוד נהיה קצת יותר ארוך זה לא דבר רע אני בדפאולט בדרך כלל הנטייה שלי תמיד הייתה לעשות איזה פייק לאחרונה הנטייה שלי היא קצת אחרת והיא אומרת ככה תכנון יותר דברים אל תהיה יותר מדי דתי בדעות שלך בקטע הזה כי [\[07:11\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=431s) ככל שאתה תכנון יותר דברים הסיכויים בדרך כלל בדברים האלה שהם expression parcing של url זה בדרך כלל לא משתנה טרקבק זה לא זהסטנדרט זה לא פורמט שמשתנה סתם בתור דוגמה למקרה הזה הספציפי אז יש מקרים שכן יש מקרים שלא זה כל דבר הוא ממש ממש ל ל ל ל ל ל ל ל לגופו ברוב המקרים אני רואה אנשים עושים לזה פייק כי זה פשוט זה הרבה יותר פשוט כי מה שאנחנו בודקים זה את האלגוריתם ואז אם זה מחזיר משהו וזה מחזיר משהו אז זה נקרא [\[07:45\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=465s) נוגם לא >> לא הפשטות האמתי ההפרדה וזה אני בגלל זה אני לא לגמרי מבין איך זה כי זה או שאתה מפריד את זה או שלא. ואם אתה לא מפריד את זה אז זה תמיד יהיה לא מופרד. תמיד כל בדיקה עכשיו של הפונקציה הזאת תכלול בוודאות את זה. >> נכון בגלל זה זה מפריע לי. לא כיף >> וזה זה ההחלטה שלכם איך לעשות את זה. אני חשוב מאוד שזא תהיה בחירה ולא משהו שהוא לא מודע. ואני חושב שזה מה שאלד אמר והוא צודק >> שצריך להיות בחירה מודעת לא לעשות את זה. לא לא לעשות את זה בגלל שלא ידעת שאתה יכול דווקא לדעת אני יכול לעשות את זה ואני בוחר לא. [\[08:20\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=500s) ואני יודע מה ההשלחות של הדבר הזה ויש לזה השלחות שאלות עוד או דברים חשובים דברים מעניינים שהגיליתם תוך כדי אני אמשיך לגבי זה אני מרגיש שאני לא לא ברור לי סטפטסט מה ההפרדה בין אסטר פארטי למשל לבין לא כלומר האם פונקציה פאבליק באותו קלאס היא מבחינתי צריכה שלה עכשיו כמו כאילו האם היא פייק פייק צריכה או או לא כלומר האם גם אם זה צריך לחלק מהבדיקה שלי או לא >> אני מרגיש שפהגם [\[08:54\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=534s) שאני עשיתי את הטestטים אני לא יודע שאני יש לי איזשהו חוק שאומר מתי כן מתי לא הבנתי אוקיי אז אני אתן לכם א' אני אתן לכם שני חוקים קודם כל אני בדרך כלל קורא פ לדברים שהם אין לי שליטה עליהם טרדים procסים דברים כאלה נגיעה בפיילסיסטם זה בטוח אני אעשה לזה פיק דבר נוסף לגבי הסקופ אתה אומר אני לא יודע מה לבדוק באיזה API לבדוק באיזה API לקבל את את התוצאה לדוגמה יש איזה שורי אומר תמיד שהאינפוטים והאוטפוטים בטסט שלך יהיו באותו לבל זאת אומרת אם בדקת בלבל של הקלאס אז תבדוק את את השאר בלבל של הקלאס אל תבדוק משהו פנימית יותר בקלאס תבדוק בלבל באותו לבל זאת אומרת מבחינת הסקורפט אם אתה בלבל מסוים אל תראה רמה אם אתה לא חייב אוקיי אז לדוגמה הסרט פארטי אם אתה ברמת הקלאס אז קלאס אחר יכול להיות סרט פארטי מבחינתך [\[09:48\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=588s) טרקבק ‏send זה דוגמה לזה נכון נסנ זה קס אחר אני אני לא חייב לעשות בפיק אבל אז הפוך להיות אגרשט test אבל אני יכול לעשות פיק לדברים בתוך טרקבק נקסנ אם אני באמת רוצה נכון אני יכול לעשות לזה אקסטר ולהפוך לטרקבק לאינסance וכל הדברים האלה אבל מבחינתי היוטור מתחיל פה ונגמר פה אז זה מבחינתי כבר לא באותו סקופ כבר בלבל אחר אוקיי זה עונה לך קצת על השאלה זה נראה יותר מה שאנחנו צריך כאילו להגדיר בתוך הריגון [\[10:23\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=623s) להגדיר בתוך הערגון לא הייתי אני לא בטוח אם צריך להגדיר בתוך הרגון חשוב שתהיו מודעים לזה שלא תמיד תהיה לכם תשובה נכונה תמיד לא תמיד יש תשובות נכונות יש לי הרבה פעמים הרבה שאלות והרבה תהיות והרבה ניסיונות זה לא משנה כמה ניסיון יהיה לכם תמיד אתם תגיעו למצב שבו לא תדעו מה דרך הכי טובה או הכי נכונה פשוט תצטרכו לנסות ומקסימום תגלו שאולי הייתם צריכים ללכת בדרך אחרת אז זאת אחת העבונות הכי מעניינות שאתה מגיע לאיזשהו שלב אתה אומר אין מצב שאני אדע תמיד מה לעשות [\[10:54\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=654s) שלב אני חייב להתחיל לקבל איזשהי החלטה וזה לא תלוי רבי אני אז אני יכול לעבוד עם עם עם זוג ואז אפשר לקבל החלטה ביחד אפשר להתייעץ עם עוד אנשים אבל זה בהחלט משהו שאפשר לעשות איתו עליו דיון לא צריך להיות בירוקרטים בנושא צריך לקבל החלטה כל נושא לגופו אסור שלדעתי שיהיה יהיה רק דרך אחת לכתוב את הטestטים האלה. צריך לתת לאנשים שקודים את הטestטים את ה את החופש לבחור את הסקופ שבו הטestטים האלה כתובים. [\[11:27\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=687s) אבל זה לא אומר שלא צריכים להיות דיונים בנושא הזה. אוקיי? כמו שיש דיונים על הנימינג יש גם דיונים על הנושא של איך לדאוק את הדבר הזה ומה הדרך הנכונה ביותר. ואתם תגלו שזה קורה הרבה. איך כדאי לי לבדוק את הדבר הזה? באיזה סקור, מאיפה נקבל את האינפוט? האם כדאי לעשות פייק לדבר הזה או לא? זה דברים שהם חלק מהעבודה. זה לא דברים שאתם אף שאתם אי פעם תעברו ותמיד יהיה לכם תשובה נוחה לי אין תשובה נוחה אז אני מניח שגם לכם אחרי זמן מסוים לא תהיה תשובה אלא אם כן תגלו מן תיאוריה של התאוריה של הכל שאומרת אה במקרה כזה תמיד תמיד תמיד כדאי לעשות ככה וככה [\[12:04\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=724s) התשובה היא שמהניסיון שלי לפעמים זה עובד לפעמים זה עובד זאת אומרת היום מקרים שבהם הייתי עושה לזה פייק ושמחתי היום מקרים שאני לא שמח לעשות את זה פייק בגלל שהגליתי הרבה יותר ערך ולא לעשות את זה לכן אין תשובה אחת זה תמיד משתנה בהתם לקונטקסט בקשר הדבר הזה הרי המתודה הזאת היא prive >> המתודה הזאת >> לא get your cont get your contct היא prate prate st >> אוקיי אז אם היא prיבט זה אומר שאני לא יכול לעשות testing שבודקים אותה >> קודם כל אתה יכול >> אם אני לא עושה את הפרט >> אתה יכול לעשות שבודקים אותה אתה יכול לעשות עם reflection אין שום בעיה לisolate יש גם apנקרא isolate הוא מפעיל לך פורים שהם prיט בלי שתעשה את כל העבודה [\[12:50\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=770s) של הבילר פלי של לעשות אבל אתה יכול היום להפעיל מה שאתה רוצה >> אז אם זה ככה אני ישנה את השאלה שלי האם באמת אנחנו צריכים להתייחס ליבט לפאבליק אחרת שאנחנו בונים טסטים >> אני מתייחס לזה אחרת בגלל שגיליתי שאם אני לא מתייחס לזה אחרת אז הטestטים שלי נהיים הרבה פחות מטם אבל יש גם הסכולה שאומרת וואלה חבר'ה אם אם באמת get your content זה פונקציה שהייתם רוצים לבדוק לבד זה אומר שהפונקציה ש צועקת לכם תהפכו אותי לפאבליק תהפכו אותי לפאבליק הלפר מט בקלאס נפרד והיא אומרת לכם שהדיזיין שלכם יכול להיות שצריך להשתנות זה בהחלט משהו שהוא ולידי להגיד אוקיי זה prיט אבל זה לא אומר שזה חייב להיות פרייט אולי אני אעשה את זה פריט ואני אכתוב לזה טestי במקרד בהחלט אפשרות אה אני אני רוצה להוסיף על זה ולהגיד אני חושב שזאת לא אפשרות עם דוקטורים שהם prיבט [\[13:39\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=819s) כאילו אני חושב שכדאי שנעבור תהליך של הגדרת קונבנציות פה של מה מה כדאי לעשות ואני אני באופן אישי הולך להיות >> בלגסיקוד זה קצת בעיה להגיד שאין אפשרות כי בלגסיק all better off >> אני לא מסכים לא מסכים איתך >> למה מה אתה הפונקציה הזאת >> הפונקציה הזאת כאילו נגיד אם אם הרגשת דגדג לך שאתה רוצה לבדוק את הקטע שמפרסר אז זה בדיוק מה שהייתי עושה הייתי עושה את זה פאבליקסטיק whatבר במקום אחר פשוט חשוף והייתי בודק אותו הלוationשן [\[14:10\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=850s) אי אפשר לקחת את האמירה שזה לגס זה המערב הפרוח ולכתוב שם טestטים שהם קקה אי אפשר לעשות את זה צריך כאילו להיות רוב הסיכויים שיהיה לכם טסטים אתם לא תהיו גאים בהם אבל הם מביאים עכשיו רמה מסוימת של ידע של משהו עובד ואחרי זה אתם יכולים לאט לאט לשנות את הקוד ואז להיפטר אחרי זה הסיבה לכתסטים יותר טובים אבל אתה לא יכול לחיות בעולם מושלם ולא יהיה לך זמן לשנות את הכל ולהפוך אותו לפאבליק וכן בעולם האמיתי שלי הייתי הופך את זה לפאבליק והייתי בודק אותו ונפרד כן לחלוקים אבל זה לא אומר שמה שנכון בקונטקט שלי נכון בקונטקסט שלכם הייתי אומר וואלה זה נכון זה משהו זה גול לשאוף אליו לא לבדוק prייטים [\[14:50\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=890s) אני לא ראיתי עולם מושלם שבו אתה תמיד עומד בעקרונות שלך בקוד של >> אני לא פשוט לא מצליח לעשות על דעתי דוגמה שבה אני לא אצליח להזיז את זה מהפרייבט אם אני רוצה לבדוק את זה >> בסדר אבל זה לא אומר שאין דוגמה יש לך >> בצות שלכם אני עוד לא מכיר אותו מספיק השאלה שלם אתה יכול לעשות את זה פבליקט בשביל שתוכל לבדוק את זה זה גם שאלה >> שמ הייתן לך דוגמה למשהו משהו שכמעט בלתי אפשרי לבדוק בלי בלי לעשות משהו ברמה שהיא לא פאבלי כשיש לך קוד שהדפendנס שלו הוא סתם הוא לא סתם קריע למשהו שהוא חיצוני אופר prיט אלא קוד שיורש ממשהו שהוא לא שאתה תלוי בו והוא לא המימוש שלך קוד שהביס שלך לדוגמה הואפ [\[15:32\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=932s) ואתה רוצה למחוק את הדependencies ואז אתה צריך להתחיל לעשות פייקים בפרי בגלל שאין לך ברירה כזה כי הטייפים שאתה יורש מהם הם prיט וסיד וכל הדברים דברים האלה ואז הם נחמות אז זה מאוד תלוי בדיזיין ובפרימוורק שאתה תלוי איתו אז ברגע שיש לך נגד קוד שחי בתוך פריימורק שהוא לא שלך זה סוג הדברים שבהם הדפנס כל כך חזק שכלים פרופיילר basols אין לך כמעט ברירה ואתה צריך מה שנקרא ממש לגדוע ככה מלמטה ולהגיד זה פייק זה פייק זה פייק הדברים האלה כל מה שהוא בטיפ הזה הם פייק גם prיטינג וגם כל הדברים האלה זה שונה ממה שדיברנו >> אתה לא יכול להפוך אותם לפסיק זה לא הקוד שלך אתה אתה אתה אתה מבלבל פה בין אתה דיברת על לקחת פרייטים ולעשות להם פייק כי זה אחלה אוקיי הוא דיבר על לקחת את הפרייט ולבדוק אותו שני דברים שונים [\[16:22\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=982s) לקחת פרייט ולבדוק אותו שנראה זה שונה וזה לא שונה גם זה יכול להיות אחד תראה זה זה לא דיון תיאורטי כן יש מקרים כאלה שאסור לך להפוך משהו לפאבליקסקיורטי טריפס כל הדברים האלה יודע להפוך משהו מאינטרנל ללא אינטרנל זה אפילו לפני פרפורמנס יכול להיות שינוקש גם >> יש יש סיבות לא להפוך משהו לוטואל אני שמעתי מפה כמה אנשים שאומרים אם תהפכו את זה לוירטואל זה יערוץ לך הרבה יותר לאט [\[16:52\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=1012s) אצלכם פרפורמנס יכול להיות משנה C++ זה מאוד משנה אז זה לא שזה הייתי נמנע מהצרות גרופות אבל הייתי אומר יש איזשהו איזשהו אידיאה לשאוף אליו וזה מין איזשהו משהו מכבה זה לא אומר לתת איזשהו אה קו אדום שאפשר להזיז אותו זה אומר שבקוד רויו אם יש ברירה אז יש ברירה עורסים אותה תמיד וזהו אבל אם אין ברירה אז אין ברירה לא צריך אה [\[17:23\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=1043s) עברתי מספיק כדי לא לתת הצרות גורפות כל העצרות הגורפות הם לא נכונות זה מה שאני אומר תמיד אוקיי כן עוד שאלות אוקיי מה שנעשה עכשיו עד סוף היום כל זוג הולך לבחור חתיכת קוד אמיתית פרודקש קוד ולנסות לבדוק אותם. אל תלכו על משהו מסובך מדי. תיקחו משהו שבא לכם לבדוק שאתם חושבים שאתם יודעים איך לגשת אליו. תבחרו משהו ששניכם נראה לכם שיהיה לכם כיף לבדוק אותו. [\[17:55\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=1075s) יכול להיות משהו שמפחיד אותכם, יכול להיות משהו שסתם מעניין אותכם לראות איך לבדוק את הדבר הזה. ואנחנו ננסה לפתור את זה עד הצופים. אוקיי? לכתוב לפחות שניים שלושה טestטים על קודקשן על הקוד האמיתי שלכם. והטestטים האלה הולכים להיכנס לסור קנטרול ולרוץ בקר >> למי שלא מודע יש פרויקט לטestטים גם בסולט וגם בסולוטו אוקיי כאילו יש כבר פרויקטים לצלם את זה >> שכבר רצים שלום אז כאילו תחברו לזה אותו דבר >> אם אני מזכיר לכם לגבי זה שיהיה לכם לשים אם אין לכם פרויקט שיש לו בשם unit test אז זה הזמן להתחיל אחד כזה [\[18:38\]](https://www.youtube.com/watch?v=8JAPnkm18-A&t=1118s) >> אוקיי כן ## Related - [Avoid testing private or protected methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_160) · The Art of Unit Testing, 3rd ed., ch. 8 Book section on avoiding testing private or protected methods, the debate the group has in this discussion. - [Pros and cons of designing for testability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 11 Pros and cons of designing for testability, matching the point that the refactorings made code testable, not better designed. - [Properties of a good unit test](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec2) · The Art of Unit Testing, 2nd ed., ch. 1 Properties of a good unit test, such as fast and in-memory, the criteria Roy uses to decide what to fake. - [Ensuring tests are part of source control](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec3) · The Art of Unit Testing, 2nd ed., ch. 7 Ensuring tests are part of source control, as the tests written by each pair are committed. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Setting up and tearing down](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9#sigil_toc_id_171), ch. 9 - [The Art of Unit Testing, Third Edition](https://www.manning.com/books/the-art-of-unit-testing-third-edition) - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 #### The Art of Unit Testing, 2nd ed. - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 #### osherove.com - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) [Previous lesson Refactoring- Introduce Instance Delegator](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/refactoring-introduce-instance-delegator/) [Last lesson Back to the course overview](https://courses.osherove.com/courses/tdd-in-net-in-hebrew/) --- title: "Legacy Code Hero" url: "https://courses.osherove.com/courses/legacy-code-hero.md" canonical: "https://courses.osherove.com/courses/legacy-code-hero/" tags: [] author: "Roy Osherove" description: "Legacy Code Hero: 5 lessons, 2 h 56 min. A free video course by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Legacy Code Hero [Courses](https://courses.osherove.com/#courses) 5 lessons 2 h 56 min 2 sections [Start course](https://courses.osherove.com/courses/legacy-code-hero/where-do-you-start-with-legacy-code/) [Watch on YouTube playlist](https://www.youtube.com/playlist?list=PLTpyQYhz5CJc) ![](https://courses.osherove.com/img/yt/XCS-9_kC6Kw.jpg) Approaching Legacy Code with a Test Driven Attitude The Problem You have been trying to learn [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)"), and it’s going pretty well, but your code looks horrible. It is really hard to test. Your design skills are lacking, and trying to let TDD drive the design without having design skills can lead to a very problematic, although testable, design of your code. Objectives I believe that separating the learning about the core skills of [Unit Testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)"), TDD, and Design should be separated so that the learner will not feel overwhelmed. This course is a complement to the Art of Unit Testing course I am teaching. This course is specifically dealing with [legacy code refactoring skills](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10 "Working with legacy code (The Art of Unit Testing, 2nd ed., ch. 10)"), and assumes that you already know how to write unit tests. Assumed: You already have some experience writing unit tests. - [Design for Testability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec2 "Design goals for testability (The Art of Unit Testing, 2nd ed., ch. 11)") - [Refactoring patterns](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") on hard to test legacy code - Writing tests against refactored code - When it does and does not make sense to refactor We will also take a look at open source projects and try to see how we would refactor them. ## About this course Roy Osherove describes [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") as [code that people are afraid to touch](https://osherove.com/blog/2005/6/5/whats-legacy-code.html "What's legacy code? (osherove.com)"), and names dependencies as its biggest problem. He covers how to choose [which classes to test first](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_221 "Where do you start adding tests? (The Art of Unit Testing, 3rd ed., ch. 12)") and how to wrap a system in acceptance and [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)") before changing it. The rest of the course shows refactorings such as [extract interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)"), [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") and instance delegator that create [seams](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec4 "Refactoring your design to be more testable (The Art of Unit Testing, 2nd ed., ch. 3)") for [fakes](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)"), with code demos that include the open-source BlogEngine.NET project. ## Related reading - [Mock Objects vs. "Inherit & Override"](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html) · osherove.com From the lesson [Extract And Override Focus](https://courses.osherove.com/courses/legacy-code-hero/extract-and-override-focus/): Roy compares mock objects with subclassing and overriding a virtual method, the technique shown slowly in this lesson. - [Where do you start adding tests?](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10#ch10lev1sec1) · The Art of Unit Testing, 2nd ed., ch. 10 From the lesson [Where Do You Start with Legacy Code?](https://courses.osherove.com/courses/legacy-code-hero/where-do-you-start-with-legacy-code/): The 2nd edition's section on where to start adding tests, ranking components by logic and dependencies as the quadrants do. - [Test Driven Validation Logic with Extract & Override](https://osherove.com/blog/2012/5/16/test-driven-validation-logic-with-extract-override.html) · osherove.com From the lesson [Extract And Override With Validation Logic](https://courses.osherove.com/courses/legacy-code-hero/extract-and-override-with-validation-logic/): Roy test-drives validation logic with extract and override, the same technique used here on the password validator. - [Refactoring your design to be more testable](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec4) · The Art of Unit Testing, 2nd ed., ch. 3 From the lesson [Refactoring Hardcore Skills](https://courses.osherove.com/courses/legacy-code-hero/refactoring-hardcore-skills/): The 2nd edition's section on refactoring a design to be testable, covering extract interface and constructor injection shown here. - [Tips for Testable code and for testing legacy code](https://osherove.com/blog/2007/6/10/tips-for-testable-code-and-for-testing-legacy-code.html) · osherove.com From the lesson [Instance Delegator Focus](https://courses.osherove.com/courses/legacy-code-hero/instance-delegator-focus/): Roy's consulting notes on getting a hard-to-test business method in legacy code under test. ## Curriculum Section 1 ### Starting Out 1 lesson · 50 min This section is a talk on deciding where to start with legacy code, based on how many dependencies and how much logic each class has and on which code is in active development or causing problems. Roy Osherove argues for covering the system with integration and acceptance tests and an automated build that runs them continuously before refactoring, with unit tests filling in later. 1. [Where Do You Start with Legacy Code? Duration 50:03](https://courses.osherove.com/courses/legacy-code-hero/where-do-you-start-with-legacy-code/) Roy Osherove discusses definitions of legacy code and why dependencies make it hard to change, then sorts classes into four quadrants by their number of dependencies and amount of logic to decide where to start testing. For most teams he recommends starting with the easy classes. He then describes wrapping a web project in smoke, security, load speed and page weight tests, built with TeamCity and FinalBuilder scripts that run Cucumber with Capybara or PhantomJS. Section 2 ### Refactoring 4 lessons · 2 h 6 min This section covers refactorings that make legacy code testable without changing its functionality, including extract interface, extract and override, parameterized constructor, break out method object, adapt parameter, static setters and instance delegator. Two lessons apply instance delegator and extract and override in detail, to a static manager class in BlogEngine.NET and to a login manager that calls static dependencies. The last lesson uses extract and override to write password validation logic with test-driven development. 2. [Refactoring Hardcore Skills Duration 46:58](https://courses.osherove.com/courses/legacy-code-hero/refactoring-hardcore-skills/) Roy Osherove goes through refactoring patterns, many of them from Michael Feathers' book Working Effectively with Legacy Code: extract interface (with a fake email sender and a look at inversion of control containers such as Microsoft's Unity), extract and override, parameterized constructor, break out method object, adapt parameter, static setters on singletons, and instance delegator on a static class from BlogEngine.NET. He closes by saying none of these refactorings can be done without acceptance tests, and that testability and good design are not the same thing. 3. [Instance Delegator Focus Duration 13:44](https://courses.osherove.com/courses/legacy-code-hero/instance-delegator-focus/) In BlogEngine.NET, Roy Osherove looks at the static Send method of a manager class, which scans a new post for links and sends trackbacks or pings, and explains why the static class and the blog settings singleton block extract and override. He copies the method into a non-static version, makes the static method forward to a new instance, and extracts virtual methods such as the enable trackback send check so a testable subclass can override them. He ends with an exercise: write unit tests for when trackbacks and ping backs get sent. 4. [Extract And Override Focus Duration 21:17](https://courses.osherove.com/courses/legacy-code-hero/extract-and-override-focus/) Roy Osherove applies extract and override to a login manager that calls a static logger: the call moves into a protected virtual method with as little logic as possible, which a testable subclass overrides to save the message for the test to check. He extends the example to a logger that throws an exception, a call to a static web service and the machine name, then shows extract and override returning fake objects. He also answers a question on whether extracted methods should be protected or public. 5. [Extract And Override With Validation Logic Duration 43:35](https://courses.osherove.com/courses/legacy-code-hero/extract-and-override-with-validation-logic/) Roy Osherove explains how to test validation code that combines many rules, using a password validator, by testing each rule separately from the logic that combines them. He introduces extract and override, also called the test specific subclass pattern, with a testable subclass that overrides the current time so a check does not have to wait seven days. He then writes a validator test first, with flags in a testable subclass that set what each rule returns, and tests a single rule method directly using the InternalsVisibleTo attribute. --- title: "Where Do You Start with Legacy Code?" url: "https://courses.osherove.com/courses/legacy-code-hero/where-do-you-start-with-legacy-code.md" canonical: "https://courses.osherove.com/courses/legacy-code-hero/where-do-you-start-with-legacy-code/" tags: [] author: "Roy Osherove" description: "Lesson 1 of 5 in Legacy Code Hero (Starting Out), 50:03. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Where Do You Start with Legacy Code? 1. [Courses](https://courses.osherove.com/#courses) 2. [Legacy Code Hero](https://courses.osherove.com/courses/legacy-code-hero/) 3. Starting Out Lesson 1 of 5 Duration: 50:03 [Watch on YouTube](https://www.youtube.com/watch?v=XCS-9_kC6Kw) In this first part, Roy discusses: - Where to start with [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") - What types of [acceptance tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_225 "Writing integration tests before refactoring (The Art of Unit Testing, 3rd ed., ch. 12)") would you run on it if it was a web application - What technologies and platforms you can use - The Anatomy of a Continuous Acceptance Test ## In this lesson Roy Osherove discusses [definitions of legacy code](https://osherove.com/blog/2005/6/5/whats-legacy-code.html "What's legacy code? (osherove.com)") and why dependencies make it hard to change, then sorts classes into [four quadrants](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_223 "Pros and cons of the easy-first strategy (The Art of Unit Testing, 3rd ed., ch. 12)") by their number of dependencies and amount of logic to decide [where to start](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_221 "Where do you start adding tests? (The Art of Unit Testing, 3rd ed., ch. 12)") testing. For most teams he recommends starting with the easy classes. He then describes wrapping a web project in smoke, security, load speed and page weight tests, built with TeamCity and FinalBuilder scripts that run Cucumber with Capybara or PhantomJS. ## Transcript 7,783 words [\[00:03\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=3s) So, my name is Roy Osherove. Thank you for inviting me. You can find me on Twitter where I post links to interesting things and there's a lot more of what we're going to talk about at arttoofunitesting.com. Now, the next two hours are going to be based on a two-day course that I do called refactoring skills for testdriven development. And we're going to maybe make 50% of the materials. We have two hours for that and I hope that we can make them in a understandable [\[00:35\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=35s) And maintain maintainable way something that you will you will actually be able to use. So that's why I'm not going over all the material because it has to be pragmatic. The agenda we're going to have is at the beginning we're going to talk about which [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10 "Working with legacy code (The Art of Unit Testing, 2nd ed., ch. 10)") do we want to test at all. How many people here work with legacy code? Okay. What is legacy code? Can anyone tell me exactly what? Nobody. Well, I'm sure you all have an idea of what legacy code is. [\[01:06\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=66s) So, I would love to hear it. This is a conversation, not a lecture. Yes. >> Code that my colleagues g >> code that you didn't write. >> What about code that you wrote six months ago and you have to maintain? Is that legacy code? >> Is that legacy code too? Okay. Anything else? So, why do you think you're working on legacy code? Okay. What's not legacy code? Maybe this will help. What's not legacy code? >> Fresh code. >> Sorry. >> Fresh code. So like two minutes ago. >> Yeah. [\[01:36\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=96s) >> So tomorrow it will be legacy code >> somehow. >> Interesting. What if what if it has tests tomorrow like you write it today with tests and you have to come back to it tomorrow. Is that still legacy code? So there are several [definitions of legacy code](https://osherove.com/blog/2005/6/5/whats-legacy-code.html "What's legacy code? (osherove.com)"). Too late sir. [\[02:08\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=128s) >> Oh interesting code that you learn something since you wrote it. Interesting. I didn't think about it like that. Maybe. Maybe. What about code that you hate? Maybe that's the definition you're looking for. So there are several definitions that are accepted. [Michael Feathers](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226 "Read Michael Feathers’ book on legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") started with the definition of legacy code as code that does not have tests. I kind of agree with this definition, but now we have he actually recanted some of this definition later and said that what he thinks legacy code is is a code that is [\[02:45\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=165s) That you are afraid to maintain. So you might have test and you're still afraid to maintain it because the tests are very brittle etc. So if I'm not mistaken that was his definition but I I'll have to look it up. But a colleague of mine said code legacy code is code that works don't touch it. And that's a lot of people view it this way. Here's some code don't touch it. It works. Therefore we call it legacy code. It's something that we are afraid to touch. We're not supposed to touch. [\[03:16\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=196s) This whole talk is what happens when you have legacy code and you have to deal with it and how do we test it without touching it and how do we approach touching it at all. So we're going to start by talking about which legacy code do we want to test at all? What do we what do we look for? Because obviously we have a lot of code. We have to start somewhere. We even test all of it maybe not. Then we'll talk about the fact that we wrap up the code with [acceptance tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-10#sigil_toc_id_178 "E2E/UI isolated tests (The Art of Unit Testing, 3rd ed., ch. 10)") before we can actually change it because if we don't have any tests and we start refactoring the code, [\[03:53\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=233s) Life begins to suck even more. Okay, so we cannot change code that is not tested in some way and integration and acceptance testing is easier than [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") on existing legacy code. And then we'll talk about refactoring the hell out of that code. Once you have [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)"), acceptance tests, then you have some confidence and you can actually change it. So we'll talk about patterns for refactoring the code and we we should have a break in the middle at some point. [\[04:25\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=265s) So let's talk about legacy code problems. Legacy code, the biggest problem legacy code is dependencies. Everything you try to do in legacy code, you want to change it and something breaks. A lot of times you can't even create instances of classes either because they are derived from other classes or because they use other classes that have a lot of dependencies. For example, you might need a lot of configuration to run a test because it uses a database or because a test uses an email [\[04:56\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=296s) Let's say an exchange server and you want to test the system. Now you need an Exchange server running or some sort of something like that. And if you want to have a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") exchange store somewhere, that's also very difficult. So it's not that it's impossible to fake things in that system, it's just very very very difficult and it takes a long time. And so the biggest problem with legacy code is that everything takes very very long to do. And when code is testable and code is welld designigned, usually it's it lends itself to testing and to changing very easily because of the way it's designed. [\[05:37\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=337s) So that means that when we look at code, we're afraid that what we're going to do, we're going to come across, we're afraid of even touching a single line of code of whatever monster is going to jump at us when we actually compile. And that's the biggest worry is that we are afraid of legacy code. We are afraid and we look at it just like we look at this spider. Can I change this method? No. I'll just copy this method, change the copy and call the copy of the method. Problem solved. And this is how code begets new code [\[06:09\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=369s) And code actually has children. So we're going to try to answer some of the following questions. Should I be testing this specific piece of code? How much value do I get by testing a specific piece of code? How much cost is there to test a specific piece of code? And to understand that I want you to think about code or your classes in two value [\[06:41\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=401s) In two value types. Here we can see dependencies on the left and logic at at the bottom. Dependencies is the amount of different classes that your class uses. For example, if your class uses a logger and an email sender, it has two dependencies. Okay? If another class uses those two plus two more classes, then it has four dependencies. So, classes with more dependencies are going to be easier or harder or harder to test. [\[07:13\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=433s) What do you think? >> Harder. obviously harder to test because you need to either fake more dependencies to test those classes or you need to change the design or maybe those dependencies are hardcoded. So it's going to be harder. So we measure the amount of dependencies per class. We also measure the amount of logic or what do you call that? The complexity there's like this weird name that I keep forgetting. Cyclomatic complexity. [\[07:43\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=463s) Cyclomatic. I always think about the I like a cyclop cyclomatic complexity for a code. So the more cyclomatic complexity or the more logic your code has, the more value you can gain from testing that code. So we can actually have [four quadrants](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_222 "Choosing a selection strategy (The Art of Unit Testing, 3rd ed., ch. 12)") where we can put our classes in. If we look at a specific assembly, we say there are classes that might have very little dependencies and very little logic. Do you have classes like that in your code? [\[08:15\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=495s) >> What what are what for example would those classes do? >> Database layer. >> Database layer forwarding mechanisms. They just do something and move it on for example facads or those things. What about classes with a lot of logic but very little dependencies? Do you have code like that? validations, algorithms, utility methods. A lot of times you'll have them in some I'm going to say manager classes [\[08:48\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=528s) Where you just have a lot of static methods. I'm not saying that's a good design. I'm just saying that's usually what happens. By the way, when you when you talk about design, don't feel bad. A lot of the companies that I go to see and visit claim that their code really sucks. their code is really disgusting no matter what I've seen before. And the truth is that most of the companies that used to be successful have really really disgusting code. [\[09:19\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=559s) Okay. So it could be that the fact that you have disgusting code is because at the beginning the product was successful or some other product in the company was successful. You didn't have time to work on it. You just had to run with it and now you're paying all the technical debt. So this ugly code is not necessarily a bad thing. It's just a necess necessity of reality sometimes. But technical debt has to be paid which is why we're doing this. So we have code with a lot of logic but no dependencies. [\[09:50\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=590s) Code with no logic and no dependencies. What about code with a lot of dependencies and no logic? >> You have such code. H >> dispatchers. dispatchers, composable objects. Would it make sense to test code like that? What do you think? We definitely don't want to test code that doesn't have logic. That will bring the least value. It's also the code least problematic. Usually, the code with with logic is the code with problems. [\[10:23\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=623s) So, the code with a lot of logic and a lot of dependencies. Do you have code like that? Yes. These are called in a lot of places God classes because nobody knows why they do what they do. They do a lot and if you do something you get punished. So it would make sense that you have only two clear paths of [where to start](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10#ch10lev1sec1 "Where do you start adding tests? (The Art of Unit Testing, 2nd ed., ch. 10)") testing. You can either test things that have a lot of dependencies and a lot of logic in which case we can say that the time to write the first few tests for those components is going to be very very high. [\[11:04\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=664s) So it's going to take you a few good days to write the first test for one of those classes. But then after you write the first few tests, maybe two or three or four, the next few tests are going to be significant significantly easier because your design will have changed to the point where it's more testable and easier to test. But there is a big initial upfront investment in trying to test these things. So I call this dependencybound strategy is because you're looking for the things with a lot of dependencies because you're trying to [\[11:40\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=700s) You know start with the big stuff and kill the big stuff first so that you're only left with the easy stuff later. And logic bound is when you try to tackle the simple stuff first and leave the difficult stuff for later. So you only try to test classes that have a lot of logic but not necessarily a lot of dependencies. maybe one or two. And this the time curve to write those tests is much much simpler. It's much easier to write a test at the beginning, but as time goes by, it's going to be harder and harder to write your tests as you achieve as you go through to new components. [\[12:18\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=738s) Okay, so these are the two basic strategies. We haven't talked about priority yet, but obviously out of all those components based on what you chose. You will only test those things that are in high priority that you are actively working on, those things that are actually part of active development today or those things that create a lot of problems for you today. If something works amazingly well and it has been living there for three years, but you have something just as complex that works really badly, [\[12:53\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=773s) You probably want to test the one that works badly first. So now the question is, what do you think is what do you think is right for you guys? Would you want to start with the difficult stuff first or the easy stuff first? I can I can play more gifts until you stop thinking. >> Easy stuff first. >> The easy stuff first. [\[13:23\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=803s) Why? >> Yeah, that's a good reason. So, you you start with the easy stuff and you count on the fact that you might learn something during the way so that when you get to the hard stuff, it's going to be easier to test. So that's actually a very good strategy if you don't have a lot of experience with testing and unit testing. So now the big question is how much experience do you guys have with unit testing and testing in particular? How many people here have been writing unit tests in the past year? [\[13:58\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=838s) Okay, that's pretty good. How many projects do we have here by the way? >> Many different >> more than 10. Definitely >> more than 50. >> Okay. So now if we have a lot of different projects the it really is important to know how many tests each product each project actually has and the reason is is based on the amount of tests that you have. Maybe you wrote a single test for each one of your 50 50 projects [\[14:32\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=872s) Or you have hundreds of tests for projects. Now based on that, based on how much experience and how much confidence you feel in writing unit tests, you might want to start with actually the difficult stuff first because the difficult stuff first is is something that a mature team, someone that has a lot of experience might tackle to change the design of the system. to start with the difficult things first will mean that the easy things will come later as the project progresses. As time constraints become thinner and thinner, you're going to have less stress and less stress. [\[15:08\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=908s) If you start with the easy stuff first, as the project progresses and time constraints become more problematic, you're going to be more stressed because you're going to get to the tough parts. However, for most teams, what I recommend is to start with the easy stuff. And there are several reasons. One of them is political. If the organization is just trying out their feet in testing and unit testing or [TDD](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)"), they're not sure whether it's a good investment. [\[15:39\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=939s) You start with the easy stuff and you show results quickly and that gives your managers the backing that they need that they're doing the right thing. If you start with the hard stuff, it's going to take a few good months to show good progress. And that only works for a company that already knows that the value of unit test and and automated testing is a big one. And most companies are not aware of that. So as a risk factor, I would say start with easy stuff and you always have developers that have less knowledge than you or have less experience. [\[16:16\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=976s) Let them pair with you as you write the new tests on the easy stuff so that they're ready when the hard stuff comes in. And then you can choose not to do it if time pressure is looming. But at least you have tests for some of those things. Now there are several tools that I used to use to to check how much [testability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec1 "Why should I care about testability in my design? (The Art of Unit Testing, 2nd ed., ch. 11)") or dependencies classes have. I wrote a cool a tool called depender. [\[16:46\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1006s) This was a long time ago that would look at a class or all the classes in in an assembly and look for testability problems like static methods etc. So you can look for that. It's open source. There's also a commercial tool called Ndepend. Do you guys use it? Have you heard of it? Some people have. Ndepend is a really powerful tool. What I like about it is that it allows you to do a visual dissection of your assembly and you can actually do queries on it like SQL. [\[17:20\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1040s) It has a language called CQL component query language. So for example, you can select all the components that have methods that use other components and then count them and aggregate them by the amount and then sort them. And that will give you something that will fit this chart. So you can actually write a query that will create something close to this although not visually. But then you can put it in Excel and create this chart from that. [\[17:52\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1072s) So although this tool costs money, I believe that it actually might do a lot of good. So I would definitely look at this tool to try to understand just how many dependency problems and how much cyclomatic complexity problems we have because it also knows how to measure cyclomatic complexity and a lot of other different things. So now that we have chosen maybe a few components, now we talk about myth [\[18:25\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1105s) Myths and and the myth is that your test should not change production code. A lot of people are afraid of changing production code and legacy code because of unit tests. But I've noticed that when I let the te the tests change the design of the production code, I get a better design. Not necessarily good design, but better than what I had. I get better readability into the code. And that's important also in terms of the maintainability later on. [\[18:59\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1139s) If you can't read the code, you cannot maintain it. So I think it's okay for tests to change the production code. For example, you want to test something, but it uses a static method, so you turn it into an interface or an instance method. For me, that doesn't actually create a problem. You want to turn a private method into a public method. I have no problem with that. Now, a lot of people do have a problem because in terms of design or component or encapsulation, this breaks what a lot of people consider object-oriented design. [\[19:32\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1172s) But testable object-oriented design is what you would call almost differing and sometimes clashing method of design. And if you think about it, there are schools of thought in terms of the in terms of at least in the software universe where there are people who believe that there are principles of solid design that are not necessarily the same as what you've been taught in terms of object-oriented design. And some of those principles were articulated by Uncle Bob Martin [\[20:07\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1207s) Who wrote them and he called them the [solid principles](https://osherove.com/blog/2013/3/6/refactoring-string-calculator-with-solid-principles-in-mind.html "Refactoring String Calculator with SOLID Principles in Mind - Examples Needed (osherove.com)") and I teach those fully there's a whole day just about this in the class but we're going to talk about them in the context of the [refactorings](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") I'm not going to cover them just as a systematic because this is not a design class this is more of a refactoring talk. So if we want to start testing our code, the first thing we have to do is to write some integration tests. [\[20:39\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1239s) Once we have integration tests, we can refactor our code into more testability and then we can write unit tests. But one of the things that I'll tell you is you might not need to write unit tests. That might sound weird from someone who wrote a book about unit testing. But if I can avoid writing unit tests and only have integration or acceptance tests and it all runs fast, I don't have a problem with that. And that's important is that you have to be pragmatic. There is no one way to do something. [\[21:10\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1270s) You don't have to be religious about the techniques that you learn. What you do is that you find what works for you and you take and you pick and choose from the things that you do. And if it doesn't work, you change it. And one of the things I'll talk about is that in the last few projects that I did which were web related projects, how many of the projects that you've worked on are web related? How many people here have worked on web related projects? About 52 and a half%. [\[21:42\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1302s) So I'm going to talk about the web rellated stuff and if you have questions about non-web related stuff, feel free to ask. But in the last two projects that I did which were web related I had less than 50 unit tests together in those two projects and all the rest of the tests were acceptance and integration tests. So now I'm going to talk about how I wrap a system with acceptance tests so that I can actually test it in or refactor it if I want to. [\[22:17\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1337s) So the first thing you have to understand about acceptance testing especially on legacy code is that it's not going to be necessarily easy because you have to try to automate the system from the outside. Now for web testing there are good tools for non-web testing there are no good tools for automating for example a desktop application and that's where the alcohol comes in. Here are the platforms I used on my last project which is an ASP.NET MVC project running on EPiServer. [\[22:52\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1372s) So we used Java to run TeamCity for [continuous integration](https://pipelinedriven.org/article/2015/5/15/time-to-main-measuring-continuous-integration "Time to Main - Measuring Continuous Integration (pipelinedriven.org)"). We use tools from CIS internals to test and deploy things. We used a tool called FinalBuilder which was written in Deli that is basically a replacement for things like MS build or ant or team system build. We used Ruby to write the acceptance tests in a tool called Cucumber. And I'll show some examples. [\[23:24\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1404s) And Cucumber is a tool that allows us to write the acceptance tests in a way that's a lot of people call behavior driven. So that we can write them almost in clear text and then we can automate the steps behind. And I and we automated the steps using a tool called Capybara which is like selenium if you know selenium only in ruby and better. And we used nodejs which is yet another technology to run a lot of tests with no browser. [\[23:57\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1437s) So we had r browser tests running where you could actually see the browser running and things being clicked on and things like that. That was using Ruby and Firefox and we used Node.js JS to run u browserless tests or zombie tests. I don't know what people call them. But the fact is that we could run tests including running JavaScript on the browsers with no browser running. And that means you can run it at a command line in a server that doesn't have a UI. [\[24:27\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1467s) And that's important. So we use a tool called Phantom.js JS to run which is which is the tool that can automate browsers with no UI on node.js and we used two other tools underneath called wislow and load speed. So when I explained this platform to the people on my team this is basically the look that I got and I'm seeing that look here right now as well. >> Yeah sure [\[24:59\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1499s) This is how we test. Okay, but not to worry, it actually is ending up pretty simple. You just have to know there are a lot of pieces that go together. That does make things a bit more complex. But I f I find that the opposite of having a single tool, let's say team system. It does everything but marginally okay is actually worse because you miss out on a lot of a lot of things that you want to test and actually the maintainability over time is worse. [\[25:36\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1536s) So you actually lose more money by not using best of breed tools like we were we did in these projects. So what types of tests did we actually have? We wanted to automate at the very least. We wanted to know that things were working, right? You have an existing system. You want to know you didn't break it before you start refactoring. So at the very least, we did smoke tests. Okay? Because if we didn't do smoke tests, we could get into a lot of crap when we change the code. Now, you could Yeah. [\[26:08\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1568s) At the beginning when I was learning how to use all these tools, this is what what it felt like. But at the beginning, we we we started with smoke tests. Okay? And smoke test a lot of the way I define smoke test is that you run something and you make sure you don't get smoke out of the machine. Okay? And for us, it meant that you run the website and you see that the website actually loads. The main page loads and you click this link, it goes to that page. and you look at the page and you see at least the header tag something loads so it didn't break you see no license errors if you're using episerver for example [\[26:43\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1603s) So those were basic smoke tests that we used just to make sure that we didn't break any configuration stuff because for example we did a lot of work with configuration and caching and all these things so we wanted to start changing all these things without being afraid because testing all that stuff manually was really really bad So there's a saying, if you hate it, automate it. Okay? And we hated doing the manual testing of those web pages and it took a long time. So we automated it. We did simple security tests. [\[27:15\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1635s) For example, we wanted to make sure that when you logged into something, it actually logs in. When you log in with the wrong password, you get a you get a failed page. And this is important because we had a continuous integration and deployment going on. So we wanted to make sure that when we changed all the configuration and we changed security based code, we didn't break our pre-production servers for example, you would still not be able to log in with the wrong user and password. You would still be able to log in with the right user and password. [\[27:45\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1665s) So we just did these automated tests that logged in through the login forms and made sure you got to see the editing page in Episerver. And when you made the wrong password, you got to see a this password was wrong page, etc. One of the requirements we had is that as we change the code, we don't make it slower because a lot of times that's what a lot of people fear is that when you change the code, what you get is more code that runs slowly. [\[28:20\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1700s) And usually this is not a non- problem a non-issue because really what happens is that you change the code and all the issues are in database related stuff and IO related stuff and has nothing to do with the virtual methods calling each other but it was a governmental project. So what we did is we had to make sure that we live up to at least no more than 1 second per page load. So we had these load speed tests making sure all the pages loaded in less than one second [\[28:57\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1737s) And of course we had weight tests. This is another requirement is that when you make you when you refactor etc you want to make sure that the pages don't go over a specific size and in this project we had for example no more than 250k. So we automated using PhantomJS and node.js JS to to measure how much a page weighs. So we had the same tests basically the same set of tests for all the pages in the system. And all we had to do was run the same set of scripts with a different URL as a parameter. [\[29:32\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1772s) So each type of tests has a simple requirement and was written with a different tool. As you can see each one gets its own face as well. I feel that one of the things that happened is that we were so busy writing all these integration tests at some point you know two months into the project someone said we don't have any unit tests and everyone was okay with that I was okay with that nobody understood why I was okay with that because you know as a consultant that teaches unit testing telling people not to do unit testing is kind of counterproductive you know it's a bit of a [\[30:10\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1810s) But there is no point in telling people to do something that they don't need to do. So if you if we got all these tests and after two months the test were fast enough where everything was just okay and we could change the code in a way that we weren't afraid to change it and it took us maybe five minutes to deploy to pre-production and to run all the tests. Maybe that's not a bad thing. So now this was a governmental project. So of course the project manager said, "Nope, you have to have at least [\[30:43\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1843s) 50% [code coverage](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html "Test Coverage and testing angles (osherove.com)") on the unit tests." Okay, but that was like a policy thing. It has it had nothing to do with the quality. So when I talked to the to the test director there and I showed the test that we had, this policy was actually changed. So the lessons that I learned in the last few projects were that not necessarily you want to start with unit tests. [\[31:15\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1875s) Unit tests should be part of filling in a bigger solution. You start with integration tests and acceptance tests and then you have a framework. You have a framework that matches the current expectation from the product that you have. Now you can start adding new tests, but these tests will actually fail. And this is test-driven development just as much as unit test is. So if you have a test that expects a page that doesn't yet load and then you write the page with everything that's needed until the test passes, [\[31:52\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1912s) That's test-driven development just as much. The cycles are bigger. So what we would do is that we would write these acceptance tests waiting for pages that don't exist yet. And then we would make the page load and we would write maybe one or two unit tests if there was a lot of logic in the page extracted into a different class. But initially we would measure ourselves based on how many acceptance tests were passing. So we would only deliver to production when the acceptance test for that new page would actually pass. [\[32:28\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1948s) And it this this actually worked really really well. in terms of integration in terms of the system that we have. This is important. All these tests are really really nice but they don't mean anything if you are the only one running them. So the first step in doing something with legacy code is to set up an [automated build](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec1 "Automated builds running automated tests (The Art of Unit Testing, 2nd ed., ch. 7)") system that continuously runs the tests. [\[32:59\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=1979s) I don't know do you guys have such a system? Yeah. Who has such a system? Okay. What what CI servers are you using? Can I >> team system? Anything else? >> Using FinalBuilder behind >> team team calling FinalBuilder. Anything else? Anyone tried anything else than team system for continuous integration ever? Okay, try it. [\[33:31\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2011s) Seriously, your job as developers is to try new things and learn new things. If you just get fed up, you know, if you get a silver spoon in your mouth by any corporation telling you to use only this tool, suspect something. Okay? So, experiment and learn that there are different tools on the market with different abilities. Now, I've successfully used Team System calling tools like FinalBuilder, but I will never ever go back to editing XML code ever again. [\[34:06\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2046s) So, if you find yourself having a continuous integration system and you have to edit XML files to make it work, like unloading your project file and editing the MS build stuff, you're doing it wrong. Okay? Don't edit XML. Look for a tool that will prevent you from editing XML. Tools like finer builder, etc. will do the work. I'm not getting paid by the guys at FinalBuilder. I'm just a happy customer. There are other tools like that. [\[34:36\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2076s) So, at the top, you can't read it, but it says TeamCity. And I've been using TeamCity for the past maybe five years. And we've been using the TeamCity as what you would use team system for which is basically to run the automated build system. But for source control we would use maybe team system itself or GitHub or or subversion but we could pick and choose. The TeamCity is really good at managing the projects and it has a free edition for up to 20 projects that you can run and it's really really good really maintainable and readable. [\[35:12\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2112s) And what we do is that we we separate the requirements of what each component does in this diagram. So the top is TeamCity and TeamCity has a specific role to play. That role is the knowledge of the system. So TeamCity knows about passwords to FTPs. It knows about the names of servers. It knows about the location of where the servers are. but it has no idea [\[35:43\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2143s) About the structure of the source code. Okay, the source code builds itself. So the the the continuous the build scripts themselves are actually part of source code. They're FinalBuilder scripts. And if you've never seen FinalBuilder, I'll try to show an image next. But imagine it's just an IDE where you can hierarchically let me see if I actually have a FinalBuilder image here. [\[36:15\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2175s) Let me see if I have that. Okay. So this is an example of a a FinalBuilder project. But let me see if I can open something a bit more interesting. >> You're all using it. >> Oh, forget I said anything. But for the video, [\[36:46\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2206s) For the people in the video who might not be using it, this is for you guys. Remember that I fought for you. Okay. Anyway, so there are hundreds of built-in tasks and, it's a highly recommended tool there. Okay, that's all I needed. Shoot me. Okay, so we're using Teamct and Teamct gets the latest version of the source control. In the source control, we have FinalBuilder scripts. [\[37:18\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2238s) Those FinalBuilder scripts have the knowledge about the structure of the source code. And because they're in version control, they have history and versioning built in. So if I wanted to build the project from three months ago, I would just get the latest version from three months ago and invoke the build script which three months ago fit exactly the structure of the code from three months ago because it is from three months ago. So this allows me to go back and forth in terms of versions [\[37:53\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2273s) And I pass in variables from TeamCity from here so that the the code doesn't care about the structure of the environment and this is very important. So I don't hardcode anything in FinalBuilder except the the relative path in the source for example the location of where to upload things the passwords and all that stuff. But then FinalBuilder would invoke Ruby or NodeJS and then run cucumber with Capybara or PhantomJS to test load and speed and weight of pages. [\[38:26\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2306s) So we had this really really big chain of responsibility but once you have that chain in place it's very easy to just change the entry points. So you want to add a new action and a new build configuration. You add one in TeamCity. You add a new FinalBuilder script at the root of the source code. You make it invoke it and then everything happens in the FinalBuilder script so that all the complicated stuff is very maintainable and very readable. [\[39:01\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2341s) Now we we used cucumber for for customer acceptance tests. Who's used cucumber? Who knows what who heard of cucumber? Okay, cucumber is a really really funny name and in the in the non-Microsoft culture, it's really customary to give really cool cool and funny names to tools. So if you have cucumber and you have capiara which by the way is a type of animal. Cucumber is a type of fruit and vegetable [\[39:33\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2373s) Veget and the point is that regardless of the names of these things they're really really helpful. Okay? So disregard the names. Don't worry about it. Now this is really the text of a cucumber feature file. So this is something dot feature and it really looks like this. This is opened in any text editor. This case you see it in Vim but it can be in notepad or sublime text or anything that you want or visual studio of course. [\[40:09\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2409s) And we have these things called features. We can write backgrounds. We can write scenarios. The scenarios are always written in a specific way. given when then and we write them in a simple language and then we translate them. We make them work by writing in the background Ruby files. So you need to know a bit of Ruby to make these things work. However, very very little and Ruby is very easy to learn. [\[40:42\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2442s) Here's another example of a feature file. And this is important because the feature names are readable and it's very easy to add more features and more scenarios and actually show this to a customer. So in my government project, I had a product owner who wanted for example for us to automate automatically test that when you check some boxes then some fields are disabled when you check this box some fields are enabled etc. [\[41:15\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2475s) So there were a lot of these requirements. So we ended up I end up saying look if I could give you this file that looks like this. When I check this then this is enabled. When I check this then that is enabled. Could you write more of these lines for me? He said awesome. Yes. That way I don't have to just come and translate to you what's in my head. And so just this one part our product owner did and he ended up with a really big feature file. [\[41:47\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2507s) But because we automated the steps, he basically just kept changing the parameters. The structure was the same. This is an example of what it's like. So if you see given the file blah blah blah, you can see given and then there is these slashes here. This in Ruby means that this is a regular expression. So match something. So given no configuration file means do the following that's in here. For example, remove [\[42:18\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2538s) Recursively all the files in a specific location or given a YAML configuration file or given a Ruby configuration file then I want you to open this config file or open this config file. So basically we're saying when the customer expects something like a number or a string that looks like this under the hood we actually accomplish a a physical task. Now it doesn't have to be creating files. We used copy which is basically saying [\[42:49\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2569s) Given main page on the website then in the given we would have visit and the URL for the main page. This is what it takes to use copy bar to visit the web page just the word visit and the URL and then we would have click to click specific things. So you can write whatever you want inside those given when then implementations but once you do you can reuse them and just change the parameters [\[43:20\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2600s) And that's the important part is that we can use this thing to create language or domain specific test language or domain specific requirement language that we can then use and parameterize and then automate. And for us it worked really nicely. But we didn't use it for all the tests. Some tests we wanted to do with PhantomJS. And I my next step would be to use these implementations to also invoke NodeJS and PhantomJS [\[43:55\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2635s) So that all our tests would be in cucumber. So that I wouldn't I always have start with Ruby. Maybe Ruby will invoke Node.js JS later, but I don't care because then I can have all the tests in the same config in the same way. Right now I have tests for Noode.js directly in FinalBuilder and all the test with Ruby in cucumber. But that was a mistake. Today I understand that I can just write the whole thing in cucumber and then automate Node.js inside the implementations instead of automating the the browser. [\[44:26\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2666s) If there are any questions just let me know. This is what TeamCity looks like with our actual projects. And look at all these build types. Okay. And all these build configurations we actually gave them in the name. We gave them a number so that the ordering would be correct because the ordering is the exact ordering what you would expect in in the life cycle of the code. [\[44:56\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2696s) So code starts out with a compilation step and then it gets deployed locally on the [build agent](https://osherove.com/blog/2010/1/14/the-difference-between-continuous-integration-tools-and-auto.html "The difference between continuous Integration tools and automated build tools (osherove.com)"). Then we have cucumber and HTML tests running on the build agent. Then it automatically also deploys to dev test and running the same tests. Then we have metrics running speed and weight and all these things happen without clicking anything. Okay. So once this happens, this happens automatically when someone compiles something and the rest automatically gets triggered when these projects finish. [\[45:31\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2731s) So so I have a trigger here that says when this build is finished successfully, get all the artifacts from this build. So don't even use source control. Use the exact binaries that were compiled by this build. copy them locally to this build configuration and then deploy those binaries that literally the same binaries that passed the test on CI or that get compiled and run tests and deploy them and then this will run the tests. [\[46:03\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2763s) This will get deployed with the exact same binaries from the artifacts here. So we can say that the tests here on this environment are in the code that has been tested here and has been deployed here. And so all of these things from the top to the bottom all use the same artifacts. So when something is in pre-production, I can say it is exactly the same binaries that we started with. It is not a different binary that got compiled. [\[46:33\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2793s) It is the exact binary that has been tested and went through all the stages. That's a very important thing because a lot of times in our in in builds an antiattern that I've also done is that for each build step I would recompile again and run all the tests from the previous builds because I wanted to know that this step is more important than the others. So I wanted to make sure it also passes all the others. So each build became longer and longer and longer. But there are better ways. [\[47:03\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2823s) And one way is to use artifacts, which by the way, it's really hard to do, if not impossible to do in a team system build. Maybe it is in 2013, but I'm not sure. This is really easy to do to have these artifacts shared by all the builds here so that I know that specific binary has passed everything before getting deployed to pre-production. But all of them do only one thing because it is already been done on the same binary. [\[47:33\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2853s) So I don't need to compile here. I don't need to run the test here. I just need to deploy. So it's maybe 30 seconds. So this whole thing can take maybe 10 minutes to go through the entire line. 10 minutes instead of five minutes. And then the next one is 6 minutes. So together that's 11. The next one does everything the rest does. So that's more and more and more. [\[48:04\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2884s) So it becomes hours. This is what the office looks like. Basically we have these panels. We have these two panels because we have developers sitting on both sides of this of the office. And we have we are using a an open source project called build screen that connects to TeamCity and shows the statuses. So here you can see there are two builds running. These are two screens on the same machine because developers on both sides needs to see what's going on at all times. [\[48:36\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2916s) This simple thing gave us such a nice confidence boost and made everyone more conscious of the fact that they are actually part of something that keeps happening. Instead of a developer that just sits there at the computer not knowing when their code will be used and what it's going to be used for, they can check in and they can see the effect that it has on the chain on in the build system and they feel like they're actually changing something. And that's is important because they are [\[49:07\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2947s) This is an example what happens when something fails. So you see deployment to pre-production failed because some guy from a different company because we have an SLA with that company. So he messed around with manually deploying things and suddenly the pre-production servers were not running. And what else? So, so, so there are there are a lot more things that I could just talk about in on those builds. I'm actually writing a book called [beautiful builds](https://osherove.com/videos/2013/5/17/video-beautiful-builds.html "Video: Beautiful Builds (osherove.com)") on this which is just about the patterns that we used in the last 10 years that I've been working on on on build related patterns. [\[49:51\]](https://www.youtube.com/watch?v=XCS-9_kC6Kw&t=2991s) So we wrap the project with integration tests and then we write test first and we write test first accept this test first and then we fill in with unit test as I said before. ## Related - [Where do you start adding tests?](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10#ch10lev1sec1) · The Art of Unit Testing, 2nd ed., ch. 10 The 2nd edition's section on where to start adding tests, ranking components by logic and dependencies as the quadrants do. - [Pros and cons of the easy-first strategy](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_223) · The Art of Unit Testing, 3rd ed., ch. 12 The 3rd edition's pros and cons of the easy-first strategy, the starting point Roy recommends for most teams. - [What's legacy code?](https://osherove.com/blog/2005/6/5/whats-legacy-code.html) · osherove.com Roy's post on what 'legacy code' really means, matching the definitions this lesson opens with. - [E2E/UI system tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-10) · The Art of Unit Testing, 3rd ed., ch. 10 The 3rd edition's section on end-to-end system tests, like the smoke and acceptance tests wrapped around the web project. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Where do you start adding tests?](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_221), ch. 12 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Writing integration tests before refactoring](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_225), ch. 12 - [Read Michael Feathers’ book on legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226), ch. 12 - [E2E/UI isolated tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-10#sigil_toc_id_178), ch. 10 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Choosing a selection strategy](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_222), ch. 12 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 #### The Art of Unit Testing, 2nd ed. - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-10), ch. 10 - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Why should I care about testability in my design?](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec1), ch. 11 - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 - [Automated builds running automated tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec1), ch. 7 #### osherove.com - [Refactoring String Calculator with SOLID Principles in Mind - Examples Needed](https://osherove.com/blog/2013/3/6/refactoring-string-calculator-with-solid-principles-in-mind.html) - [Test Coverage and testing angles](https://osherove.com/blog/2005/4/3/test-coverage-and-testing-angles.html) - [The difference between continuous Integration tools and automated build tools](https://osherove.com/blog/2010/1/14/the-difference-between-continuous-integration-tools-and-auto.html) - [Video: Beautiful Builds](https://osherove.com/videos/2013/5/17/video-beautiful-builds.html) #### pipelinedriven.org - [Time to Main - Measuring Continuous Integration](https://pipelinedriven.org/article/2015/5/15/time-to-main-measuring-continuous-integration) [Next lesson Refactoring Hardcore Skills](https://courses.osherove.com/courses/legacy-code-hero/refactoring-hardcore-skills/) --- title: "Refactoring Hardcore Skills" url: "https://courses.osherove.com/courses/legacy-code-hero/refactoring-hardcore-skills.md" canonical: "https://courses.osherove.com/courses/legacy-code-hero/refactoring-hardcore-skills/" tags: [] author: "Roy Osherove" description: "Lesson 2 of 5 in Legacy Code Hero (Refactoring), 46:58. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Refactoring Hardcore Skills 1. [Courses](https://courses.osherove.com/#courses) 2. [Legacy Code Hero](https://courses.osherove.com/courses/legacy-code-hero/) 3. Refactoring Lesson 2 of 5 Duration: 46:58 [Watch on YouTube](https://www.youtube.com/watch?v=NYex4JKEczo) In this talk we take a long deep look at many different [refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)"), including: [Extract & Override](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html "Mock Objects vs. \"Inherit & Override\" (osherove.com)"), [Extract Interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)"), Instance Delegator, Parametrize Constructor, Add Static Setter, and many more. ## In this lesson Roy Osherove goes through [refactoring patterns](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec4 "Refactoring your design to be more testable (The Art of Unit Testing, 2nd ed., ch. 3)"), many of them from [Michael Feathers'](https://osherove.com/blog/2009/8/18/ndc-video-michael-feathers-working-effectively-with-legacy-c.html "NDC Video – Michael Feathers – Working Effectively with Legacy Code (osherove.com)") book [Working Effectively with Legacy Code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226 "Read Michael Feathers’ book on legacy code (The Art of Unit Testing, 3rd ed., ch. 12)"): [extract interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)") (with a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") email sender and a look at [inversion of control containers](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_65 "Dependencies, injections, and control (The Art of Unit Testing, 3rd ed., ch. 3)") such as Microsoft's Unity), [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)"), parameterized constructor, break out method object, adapt parameter, static setters on singletons, and instance delegator on a static class from BlogEngine.NET. He closes by saying none of these refactorings can be done without [acceptance tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_225 "Writing integration tests before refactoring (The Art of Unit Testing, 3rd ed., ch. 12)"), and that [testability and good design](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec3 "Pros and cons of designing for testability (The Art of Unit Testing, 2nd ed., ch. 11)") are not the same thing. ## Transcript 6,848 words [\[00:03\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=3s) Now the patterns I'm going to show here a lot of them are taken from a book called [Working Effectively with Legacy Code](https://osherove.com/blog/2005/4/15/book-of-the-month-working-effectively-with-legacy-code.html "[Book of the month] Working effectively with legacy code (osherove.com)") by [Michael Feathers](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226 "Read Michael Feathers’ book on legacy code (The Art of Unit Testing, 3rd ed., ch. 12)"). How many of you know this book? Okay, more of you should know this book. Okay, this book is worth its weight in gold. Okay, this is one of the books that for me helped to to clear a lot of the techniques that I've been using. So I owe a lot to Michael for for writing this book. [\[00:35\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=35s) It's the reason I asked him to write the forward for my unit testing book. So the first refactoring and the easiest refactoring you can make is [extract interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74 "Extracting a common interface (The Art of Unit Testing, 3rd ed., ch. 3)") and a lot of you probably already did it. However, in [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") situation, this is also the safest refactoring because it changes very little in terms of the the structure of the code and the signature of the code being used. And if we talk about legacy called refactoring, we have to consider two parties. We have the party that you're changing. [\[01:06\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=66s) That's the class that you hate. But then you have all the classes that already depend on the class that you hate. They will hate you back if you change the signature. So changing the signature is one of the worst or hardest things you could do. Not necessarily worst. We're going to see some patterns for also changing the signature, but in terms of ease, you want to change the sign signature less. Sometimes changing the signature is a great idea, but it takes a long time because there are a lot of people or classes depending on it. [\[01:40\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=100s) So extract interface here. Here's a simple example. Let's say that you have a class called storage. Storage takes an email sender as a parameter to the constructor. Or maybe it doesn't even take a parameter. Maybe it just uses new email sender at the beginning. And you want to test that storage actually sends an email when you call save. But the big question is how the hell are you going to do that? Because email sender is a hard dependency and it actually uses the real system. [\[02:14\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=134s) There is no way to replace it. So one way to replace things in languages like net and java is to have an interface. So we introduce create a new interface in the system called I email sender with exactly the same signature and we replace the signature of the constructor in a way that doesn't hurt everyone that depends on it because email sender will also implement this interface. So we just add to email sender. Everything else that uses this class will not have to change. [\[02:48\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=168s) But we get what's called a [seam](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec4 "Refactoring your design to be more testable (The Art of Unit Testing, 2nd ed., ch. 3)") seam. Sea m a seam is something that allows us in our code to test or to replace things. And in this case, having a parameter that's an interface into the constructor allows us to create in our test classes a [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") email sender. So in our code, in our test code, we could create a new class that implements from I email sender as well. [\[03:20\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=200s) However, it will not really send an email. It will just simply implement the interface. And when someone says send email, the send email class will just be an empty class and we'll just save the values. So it's it's a fake email sender. Now we can use this one and send it into storage and storage wouldn't be any wiser. It will just work the same way it did. Production code will work the same way it did. So we refactored the code. So what's the definition of refactoring [\[03:59\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=239s) That's why we pay you. Okay. Yes. >> Same functionality another way. >> Same functionality structured another way. That's a great definition. So changing the code without changing the functionality. Perfect. Pay this guy. Now this is important because when we refactor the last thing we want to do is change functionality because that's a very risky thing. We usually don't have tests, but if we had [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)"), checking the functionality, we might catch it, but it's still a very risky thing to do. [\[04:34\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=274s) So, changing functionality is something that we only do in a [test-driven](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") way. Changing the structure of the code we can do without adding specifically new tests. Here we're changing the structure so that we can add new tests and so that later we can add new functionality. For example, email sender needs to be called twice. But I want to write a test that it's only called that that it should be called twice that fails because it's only called once currently. So for that I will introduce a new interface, create a fake email sender and then I can write a test that says that fake email sender should be called twice but it's called only once. [\[05:13\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=313s) Okay. And then this test will fail and then I can add the new functionality which calls it two times. So there is a process here. Here is an example. Class storage takes an email sender. We change the constructor so that now storage doesn't care what is the type of email sender that it has as a private variable and it takes an interface as a parameter. And then in our tests I can basically send in a new fake email sender [\[05:44\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=344s) And then call save. And then I can test the result or I can I can assert on something here. This is the fake email sender in my tests. So I can actually do nothing or I can save the message here, put it in a public variable and then assert on it in my test. I can create this on top and then assert against it at the bottom. So I can use it almost like a spy that says, "Hey, go in and tell me what happened to you." This is me using the theme. [\[06:17\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=377s) However, when we introduce this interface and what I noticed is that a lot of teams they they they see extract interface and everything, you know, they have a hammer, everything becomes a nail. And so you see these systems that are very very very testable where you have hundreds of interfaces all over the place almost, you know, the worst case is where someone almost created an I integer, you know, but [\[06:50\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=410s) But think about it is that this becomes a bigger problem over time. In this case, person logic maybe or storage takes two interfaces. So now in the code, everyone who uses person logic now has to create two objects in know in order to create person logic. That's easy. But what if to create a logger, you also need to have to create another couple of objects because each object has its own dependency. What if to create a logger you need an exception handler and a data writer and to create a validator you need to know to have an I overridable somewhere in a dependency and to create the handler and the overrider you need three new dependencies. [\[07:30\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=450s) So now to create this simple person logic you need nine lines of code in your production code just to create this thing. So now you have to create these factory methods. that's okay too. But this is where things like [dependency injection](https://osherove.com/blog/2008/1/18/dependency-injection-is-it-relevant-beyond-unit-testing.html "Dependency Injection - Is it relevant beyond unit testing? (osherove.com)") containers come into play and they help a lot with this problem. So there are a lot of inversion of control containers innet. The three that a lot of people use I see using is structure map unity and ninjage [\[08:05\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=485s) May vary. Has anyone here ever used one of these or a different one? Which one have you used? >> Castle. Castle Windsor. That's Castle Windsor is a is an older one that's very widely used, but it's a bit long in the tooth in a way. So, it's getting older in terms of API and the new ones have a better fluent API that to me is nicer and easier to understand. A lot of times, especially since some of them are inherited from Java, you have to configure them via XML and I hate XML. [\[08:39\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=519s) So, a lot of the new ones, including structure map and inject and unity, you can configure directly via code with no configuration whatsoever in files. And to me, that's much more maintainable. So here's an example. If we have these two two dependencies, we could create a container. Now, this is a test that uses the Microsoft Unity container. But you you don't necessarily want to use a container in a test or in production code directly. [\[09:13\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=553s) You want to usually abstract it away. But this is to show how you use a container. So in this case the Unity container from Microsoft which is an open source project you call register type of I logger set it to fake logger. So if I think about it it's really a smart factory method at the beginning you say look when someone when when someone requires a type and that type needs an i logger give it them a fake logger implementation when someone needs a person validator give them a fake testing valid [\[09:46\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=586s) Testing validator. So now if I want to create an instance of person logic b testable which is for my demos I say unity container.resolve and give me an instance of this. I don't say new I just say resolve to the container and the container will take care of everything that's going on in terms of dependencies. And if you've been to one of Mark Seaman's talks he has a tool called autofixure for unit tests. And autofixure in a way [\[10:18\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=618s) Works the same way is that it allows you to not think about the signature of the constructor of an object. It will just fill up what's necessary with default fake objects for tests. In this case, this is something that we might use for production. So in production, we wouldn't use fake logger. We would say if anyone in our production code ever wants a logger, they should call resolve or whatever the infrastructure forwards to resolve and say give me something that looks like a logger. [\[10:50\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=650s) And if logger has a dependency and the dependency has a dependency etc recursively, this will just work in a single line of code and that saves a lot of typing time and understanding. This also gives you very nice flexibility because if tomorrow you want to add a new dependency into your code, you simply put it in the constructor and if the container is already configured to use that dependency, this type or interface, then you automatically get it. [\[11:20\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=680s) You say, "Oh, I need a service configurator." put it in the constructor as a parameter and at runtime magically you have it because someone calls resolve container already knows how to give an iervice something and you don't have to change the signature of anyone that calls you so it does give a lot of flexibility so if you do do a lot of extract interface at some point you might have to start facing the reality of IOC containers [\[11:50\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=710s) Now I personally have not used them too I find that when I have a lot of these parameters, I tend to group them all together into a single object. So a common refactoring that I do is when I have three parameters or more, I create a single parameter of an object with those parameters as properties. Okay, that's called parameterized constructor or a create a method object. Not not method object. I I I not I'm I I not remember. I don't remember. [\[12:22\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=742s) I not remember. Sorry. Okay. So when you do talk about containers, you shouldn't use them directly in production code because there is that creates another dependency on something and the whole point is that you use containers that you stop wanting dependencies. So it's kind of defeats the purpose. Some people say oh and then it it will be harder to change a container later. I've never seen a project that wants to change a container after a year. [\[12:57\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=777s) Okay, the next the next piece of code is a different kind of refactoring. It's a bit more advanced in that it requires a bit more understanding in terms of inheritance etc. [Extract and override](https://osherove.com/blog/2012/5/16/test-driven-validation-logic-with-extract-override.html "Test Driven Validation Logic with Extract & Override (osherove.com)"). How many people here read my book by the way just so I know. Okay, so you got the book. That's a good first step. [\[13:29\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=809s) Okay. So, extract and override is you see all these words written here? Forget about that for a second. Let's I'll show you a demo. Okay. Okay. What should we do? [\[14:08\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=848s) Okay. Yes. Yes. Yes. Okay. So, here's an example of extract and override. Extract and override is powerful for almost any situation. That's why I call it extract and override because it's almost too easy to use. At the beginning, it looks a bit convoluted, but when you get used to it, it's very simple. So, here's an example of a method called is login okay. It takes a user and a password [\[14:40\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=880s) And it has a dependency on static logger. Now I want to write a test that proves that it calls the logger but logger is static. I cannot replace it and I'm not using a tool like typemach isolator or moles or anything like that. How do I do that? And the act the answer is I cannot without refactoring this code. So how can I refactor this code to test that the static logger was called? I can refactor it into one more level of abstraction. [\[15:10\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=910s) And I'm going to say this. If we have this line, I can extract a method. I can make it virtual and I can say I can call it call logger. Okay. However, it's not good enough yet because this method because it's virtual. [\[15:42\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=942s) What's going to happen is that in my tests, I will want to override this. That's why it's called extract and override. I'm extracting a method. This method calls directly to the static logger. But I also want to test the variables being sent. So I'm going to extract a parameter here. I'm using, by the way, ReSharper. Who has ReSharper installed? Okay. Who knows more than 50% of the shortcuts in ReSharper? Okay. If you have a tool and you don't know all the stuff that you can do with it, [\[16:15\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=975s) That's a waste. Okay. >> probably 90. Okay. So, let's say login requested. I'm going to change it to text. And now I already extracted this method, so I'm just going to use the one I extracted before. But it looks exactly like this. Now you can see that I refactored the code but the functionality has not changed. So if I go back [\[16:45\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1005s) To the what the hell if I go back to the usages of the code I can see that we just have this call logger with the variable and that's very good for me because I don't want to change the functionality. However, I've created a scene. So, if I had a scene before where I had an interface I could replace, now I have a virtual method that I can override. That's a different type of scene. [\[17:15\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1035s) Okay. So if I go to a class and I say login manager login manager lm with tests manual login manager with statics and I say I create a class called testable login manager with statics. Let's do that all over again. [\[17:55\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1075s) So let's say I create a class here. Class testable testable version of login manager. Login manager with statics inherits from login manager with statics. Now this is important. I'm extracting I have to override it somewhere. So what I'm going to do is I'm going to create the exact login manager with statics with only one method being fake. [\[18:26\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1106s) To do that I override call logger and I don't call the base. Now what happens is that production code calls logger but logger doesn't do anything. So maybe I can do something here. I can say maybe create a public property and say text written [\[19:02\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1142s) Let's do that into a field. Create field and make that into a public. This is what I did. Now this this is all I have to do right now to create a testable version of login manager with statics. Now I have to use it in my test. So I'm going to create a new test here. Test. This is by the way a macro that you can do in re sharper. This is the macro that I use to create my unit tests. If you want to know how I do it, just let me know and I'll show you. [\[19:36\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1176s) Okay, one person not enough. and [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)") is the thing that I'm testing on. So I'm going to say is login. Okay, this is the [entry point](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18 "Entry points and exit points (The Art of Unit Testing, 3rd ed., ch. 1)") of my unit test, the public method that starts the unit of work, the use case. And I want to test that it always calls static logger. What else? Now what I'd like to do is to say var lm equals new testable login manager with statics. [\[20:14\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1214s) So instead of creating the actual login manager, I create the testable version of it and I can count that the test that the testable version works exactly like the real one because it inherits from it with only a single method turned off. Then I can simply say lm is login okay with a user and a password and assert is not null for lm.ext. [\[20:49\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1249s) So I'm actually asserting on a property on the object I'm testing but the property is only specifically from the test domain. So in production this text written thing doesn't exist. this only exists in my test domain. So I created a testable version of this. So again what I did is that I created a virtual method that I can override in a testable version of the same object and then I used the testable version of the object with the logger turned off to check what text was being sent to the logger. [\[21:20\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1280s) Okay, it seems complex at first. You have to do it a couple of times. What happens is that once you do it, you get the hint of it and then you can break almost anything with this thing. Almost anything questions. Let's talk about [\[21:54\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1314s) Okay just like we extract and override a call to a logger we can also extract and override a call that creates an object. So let's say that we have a dependency on an email that gets created directly in the code. So we have a workflow engine and in the workflow engine we have new transaction manager being created and to be to create it you need a new model reader and an XML store and all that stuff is a bunch of dependencies. It's very very difficult to actually test this and this all happens in the constructor. [\[22:29\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1349s) So even creating this class has a dependency on the file system. So it can't really be a unit test and it requires us to have configuration files in the right place and maybe use a lot of app settings to do stuff. So we can take this whole selected piece of code and extract it into a factory method that is virtual that we can override. This will not work in C++ by the way but it works perfectly fine in C. So instead of all this stuff, I created a protected virtual make transaction manager. [\[23:04\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1384s) It works exactly the same way. I did not change the functionality in any way. However, it's virtual. So in my tests, I can now create a testable workflow engine. And in the testable workflow engine, I can override making a transaction manager and return a fake one. And now I can maybe assert things on it or recreate conditions. For example, how can you test what happens when your code encounters a memory violation? [\[23:40\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1420s) So I can make the fake transaction manager do whatever I want. It's my code. It's in my tests. I can put whatever fields and booleans on top of it. It's my own class. So extract and override works for creating objects. It works for calling objects. It can also work for future objects. So this code hasn't been created yet, but I can control the instances of objects directly created through refactory methods. Can return different objects. I can return the same object. [\[24:10\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1450s) I don't I don't really care questions. Okay, here's a simple one. Parameterized constructor. So parameterized constructor is something a lot of us take for granted. But sometimes in legacy code the dependencies are created just like here we have the transaction manager being sent in not not being sent in but created. [\[24:42\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1482s) But we could just as well create a parameter for the constructor and make it a dependency that you can send in or inject. So you can create a [constructor injection](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_72 "Constructor injection (The Art of Unit Testing, 3rd ed., ch. 3)") pattern here just like we did before. So we can create an interface or just create the class and make it a parameter and then make the class an interface. Here's a one a bit more interesting. Break out the method object. Breakout method object. Let me see. [\[25:15\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1515s) Break out method object. Breaking out a method object is what you do when you have a public method that uses a lot of private methods. This is example, by the way, is in C++. I hope you guys can still read it. I know it looks like a bunch of characters swearing in The Simpsons or something, which is the reason I don't like C++ so much. [\[25:45\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1545s) However, it's a good example because here we have a class called GDI brush and we have a method called draw and it uses a lot of private methods and it shares the same variables and the same fields with it and that creates a very tough thing to test and the and the class is very very long to test. So instead what we could do is we create a whole new class called renderer and the renderer will take the original class and all the variables that the public method and all the private methods used [\[26:18\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1578s) And it will use them as fields in the new class. So, so we create a class just for that one public method and all its private methods because what it does this way it allows us to test just the functionality of that method without interfering with all the other methods in the class. So we so we so we end up with a class that looks like this. We we have this method draw. It actually calls the renderer and it calls draw on the renderer. [\[26:50\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1610s) So this is the method that's actually that can actually be tested one and and now and this method has all all the private methods that it needs but none of the other methods from the original class. So it's cleaner. Okay. So if a method uses three or four sub methods in the class and the class is huge, you take one method at a time with all the things it relates to and put them in a separate class and you make all the variables it shares in the class as public fields or private fields in the new class and that and then the original class just calls the new class in a single in a single line of code. [\[27:28\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1648s) That makes things much more testable, cleaner to read. Okay, adapt parameter. Let's see if I have Okay, adapt parameter is is one of those signature changing techniques. Now the the signature here has to change if we want to cover one of those [solid principles](https://osherove.com/blog/2013/3/6/refactoring-string-calculator-with-solid-principles-in-mind.html "Refactoring String Calculator with SOLID Principles in Mind - Examples Needed (osherove.com)"), solid design principles that you can hear about from Uncle Bob. [\[28:07\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1687s) Let me show you the the principle itself. It follows the interface segregation principle and the idea is that no client should be forced to depend on methods that it does not use. So let's say that your method relies on HTTP context. In this case, this is Java, so it uses HTTP server request, but it just might as well be HTTP context. HTTP context has how many methods do you know? [\[28:38\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1718s) 117. I have no idea how many, but definitely around that. And here in this class called arm dispatcher it only uses a single method of that class to do its bidding. So what we do is we say okay let's use the interface segregation. We only need to use a single method and that gives us the ability to refactor and wrap it in an interface that only has a single method. So we can create [\[29:10\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1750s) An interface called I parameter source which has a method called get parameter for name and I parameter source will use the HTTP serlet but and it will use whatever it needs inside it but it only has this one method and inside it will use whatever serlet method it needs. This is important because this means that we wrap the dependencies of our classes with only the methods that are needed by those classes. [\[29:43\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1783s) So it's easier to fake. For example, it's much harder to fake a class or an interface with 100 methods than an interface with a single method. Okay? And if tomorrow we don't rely on HTTP server but on something else, it's very easy to change the production code, but our tests will not break. So the more chatty our interface is, the more likely we will want to to change the signature and say we don't need something with all those 20 methods when we only use three of those. Let's create an interface with only three of those methods or maybe a single one that uses those three [\[30:20\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1820s) As an adapter and use that one in the new class in the class that we're testing. And again, if there are any questions, just let me know. This this exercise is it only for testing purposes to do this? >> No, this is not necessarily for testing purposes. This is a basically a design technique although it helps with testing >> but but you use for for instance standard.net objects >> I would >> does it make sense to wrap all these >> does it make sense to wrap? [\[30:52\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1852s) Well sometimes it makes sense and sometimes it doesn't. If the interface is very chatty, there is a big chance that tomorrow someone's going to use another extra method just because they can and then you have to fake another method and then you have 50 breaking tests. So in terms of maintainability, it can help you a lot because in terms of maintainability, you wrap this whole thing in an adapter class. Then the adapter class only has a single method or two. So it's much easier for testing. So, but as a general rule, you're going to have a harder time or more brittle tests [\[31:25\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1885s) When you use fake objects that have a lot of methods. Doesn't really matter if it's net or not. Okay? Even if it's your own classes and they have 20 methods and they only get used by only two of them get used by your by an object, it usually means something. It means that maybe you don't have a single responsibility principle in those classes. it means that that class works both as something for this class and the other 18 methods work as something different from another class. So it usually means you want to break things up [\[31:57\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1917s) But at the very least you want to adapt a class specifically for your class. So it's a single responsibility principle as well in action here. other questions and then then in your test you can create an IP a fake parameter source that you can fake the value to return can create a new fake parameter source set the property to return whatever you want and that gets used here. [\[32:35\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1955s) Now static setters there's something that a lot of us are afraid to do. So imagine you have a simple singleton class. Okay, here's a singleton class. Not a very good implementation, but who cares? Singleton is a singleton. Who knows what a singleton is? Okay, for those who don't, a singleton is a class that only has a single instance and it and it it prevents you from creating new instances of that class. So in this case it's message router. If I want to use its instance I would say message router.instance [\[33:09\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=1989s) Which is a static method that automatically creates a message router and it has a private constructor. So I cannot create it directly. Now in this case the big problem is what happens if message router has a dependency on the file system or configuration files or all that stuff. How can I break those dependencies? How can I create my own fake message router if someone else is using it or I want to test that message router gets called? [\[33:39\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2019s) One simple way to do it is to not just have a public getter but also to have a public setter which of course defeats the whole purpose of a singleton which is why a lot of people don't like it but I don't have a problem with it because I'm not religious about these things. However, for those people who are who really really care that and they're afraid that their users of the API will use it wrongly, [\[34:10\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2050s) You have to remember two things. First of all, if you are only relying on your API, if unless you're creating an a framework that's going to be used by people all over the world, if your framework is going to be used only by people in your company and you're not sitting with them and doing [code reviews](https://osherove.com/blog/2007/3/13/test-reviews-vs-code-reviews-some-helpful-tips.html "Test Reviews Vs. Code Reviews - Some Helpful Tips (osherove.com)") and you're just relying on your API to tell people how to use your code, they're going to misuse your code anyway. Second of all, one of the nice lessons I've learned from other people is that when you leave things open, [\[34:41\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2081s) You're going to get nice surprises of how people use your API so that they use it the way they need to use it instead of the way you designed to use it. It helps them even more. So, if they can override things that you didn't even plan that they can override, that's not necessarily a bad thing. You think it's a bad thing because in your head you're a control freak. But having overridability for things you cannot even imagine now that will happen in two years is something that I really like having. But let's say you still don't want to do it. [\[35:12\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2112s) This is what I would do. Instead of having message router instance, I would put a public setter called set testing instance. I would have the word testing in there and I would put the conditional on it. This only gets compiled if the unit test or let's say debug compilation flag is on. And this allows me to only have this during running tests and it doesn't actually get included in production code. [\[35:43\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2143s) Simple. This way everyone's happy. I'm happy because I can test this thing. Control freaks are happy because it doesn't exist really in production code questions. Okay, now here is a complex one. Instance delegator. Instance delegator is this is the one place you're going to have a hard time if you get out now. Just so you know, [\[36:15\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2175s) Too late. There is there is this pattern that a lot of actual users of ReSharper like to do and that is to let ReSharper dictate whether a method is supposed to be static etc. And so you get all these statics all over the place. So here's an example. Here's a this is from an open-source project called BlogEngine.NET. And BlogEngine.NET net somewhere deep inside it has a static class called manager. [\[36:51\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2211s) Why is it static? Nobody knows. What is the static actually mean on classes? Do you know? >> All methods have to be static. Why do all methods have to be static? Nobody knows. So you actually remove room for methods that are not static in this class. We'll talk about why that's bad. And then you have a static send method. [\[37:22\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2242s) Okay. Now, now just to explain the the manager has a send method that takes an I publishable. Look, it's an interface everyone. And I publishable is a blog post. And then it has a bunch of stuff like it looks at the blog settings instance. Notice how that's a singleton right there. I want to test the send method. I want to test for example that when I when there are URLs in the item content that I send in then if the blog settings is true then it does something. [\[37:56\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2276s) It calls something but everything is static here. I cannot use extract and override. For example, this method here is private static. Now, private static is an example of someone who just extracted a method and it's static by default. But if it was an instance method, I could make it virtual and then I could override it and fake the URLs from the content. I could also if this whole class was not static and this method was an instance method, I could extract this whole thing into a virtual method and say [\[38:32\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2312s) Fake that block settings returns false or true by extracting override on this piece of code. But I can't because this method is static. So we cannot use virtual methods. So there's nothing I can do to replace anything. To be able to even start refactoring and replacing things, I have to make this method an instance method. And for that to be an instance method, it has to be a non-static class. [\[39:03\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2343s) So in this case, I wouldn't have no trouble of removing the static keyword. It doesn't change the signature of anything. No code that uses this class will break. It doesn't break. This is only an implementation issue of this class and it just hurts our [testability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec1 "Why should I care about testability in my design? (The Art of Unit Testing, 2nd ed., ch. 11)"). Let's see if I can go to manager here. [\[39:37\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2377s) And what we want to do is to try to refactor this. And so what I'm going to do is I'm going to create a forwarding mechanism into a an instance method. Now remember, one of the worst thing I can do is to change the signature for everyone else who's already using this class. So my primary purpose is to make this testable and still keep the signature. [\[40:07\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2407s) And this miracle can happen if I remove the static keyword and I duplicate the method. So I have now two methods called send. Now compiler won't let me do that. So I'm going to say send internal or maybe send instance and this one method [\[40:40\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2440s) Is not going to be static. Now this is the original method and I made it non-static. What about the static signature? It's going to be a forwarding mechanism. It's going to say new manager dot send instance of item and item URL. This is the beginning of my refactoring. So I've made the class an instance class. Everyone else who's already using the static method will still be able to use the static method because the functionality has not changed. [\[41:18\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2478s) All everything that happens is that now it uses an instance and that instance still uses the same exact methods. Look at this. Right? This is not an easy method to test. But I can take now that it's an instance method, I can start taking advantage of things like extract and override because now this method is running in an instance of a class. So for example, let's say this is a dependency obviously this is a singleton. Let's say I want to make sure without needing a configuration file in my tests [\[41:51\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2511s) That enable trackback send is always going to be true. So I can extract and override this stuff into a method. Ctrl Alt M in this case. Make a method make it not static. Make it virtual. And now it looks like this. if enable trackback send. Now in my tests I will have a testable manager class that overrides enable trackback send and instead of this implementation it will just have a field that I set in my test to return true or false also whatever I care. [\[42:31\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2551s) So now I have full control. So from being a fully untestable piece of code this has now become a very testable piece of code. And now what about all this stuff? Get URLs from content. This is a private static method. Private static means that nobody else is using it. So there is no harm in me removing the static. There's no harm. Nobody else is using it. Only instance methods [\[43:01\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2581s) Which they don't mind using static methods and they're only in this class because this is a private method. So there's no harm in removing the static and making it virtual and making it protected like this. Now this allows me to do more cool stuff like fake that I have two URLs in the content or zero etc. Instead of creating content with URLs that are very very complicated, I can just return whatever fakes that I want. [\[43:36\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2616s) So again what I did is that I took an original static method. I created a copy of it. I made the original non-static and the copy of it I simply forwarded to say new class called the non-static version. So now I have an instance delegator. It delegates the call to an instance with exactly the same parameters. And that gives me the flexibility to extract an override or introduce interfaces or whatever I want. [\[44:10\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2650s) Questions? Yeah. >> What if there was some kind of member variable inside that class that was static that needed to be static because let's say some data was fetched from the database that you want to make sure it was only fetched once and was reused again and again while restoring your member variable. So what if there was >> what if there was a member variable that was static that you needed in this class >> that you wanted to set from the database but only once and then you would not go to the database anymore retrieve that value from the static so it had to be static. [\[44:41\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2681s) >> Mhm. >> Would you have an issue because now you started making things into instances instead of static. So I'm I'm not sure that I understood the the the end result that you're looking for and how we would refactor, but usually with a combination of either extract and override or extract the factory method of the thing that you're trying to get or just having control a public setter on the static member that you can control then you can get around those things. But I would have to look at the exact code. Maybe you can do it after the talk. [\[45:12\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2712s) But but you understand the I >> I don't understand the exact issue but I don't want to get into it too much now but we can do it after because it sounds like it's a bit more complicated than this and this is complicated enough. Okay. But I haven't seen yet an issue that I cannot overcome with the combination of these methods. Okay. Other questions. Okay. Let's see. [\[45:53\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2753s) Okay so in summary what I want to say is that legacy code is hard alcohol is good however all these stuff that all the refactoring stuff that I just told you about you cannot do them without the [acceptance test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-10#sigil_toc_id_178 "E2E/UI isolated tests (The Art of Unit Testing, 3rd ed., ch. 10)") so if there's one thing that you have to start with is not even do the refactoring. Overcome by by by not overruling by bypass all the refactoring and the unit testing stuff at the beginning and start with acceptance testing and see what you end up with. [\[46:24\]](https://www.youtube.com/watch?v=NYex4JKEczo&t=2784s) You might end up with exactly what you wanted, which is a tested system that you can change without going to the trouble of refactoring the hell out of it later because then you can refactor to whatever you want. Not just for testability, but just for better design. Whatever you want. Testability and better design are not necessarily the same thing. They don't always mean exactly the other, okay? But they sometimes overlap. So don't mistake testability with great design. Okay? Design is a separate skill from writing unit tests. ## Related - [Refactoring your design to be more testable](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec4) · The Art of Unit Testing, 2nd ed., ch. 3 The 2nd edition's section on refactoring a design to be testable, covering extract interface and constructor injection shown here. - [Extracting a common interface](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_74) · The Art of Unit Testing, 3rd ed., ch. 3 The 3rd edition's section on extracting a common interface, the first refactoring Roy applies to the email sender. - [Issues in breaking dependencies for unit testing](https://osherove.com/blog/2005/8/23/issues-in-breaking-dependencies-for-unit-testing.html) · osherove.com Roy on the different ways of breaking dependencies in legacy code, the set of refactorings this talk walks through. - [Read Michael Feathers’ book on legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226) · The Art of Unit Testing, 3rd ed., ch. 12 The 3rd edition's pointer to Michael Feathers' legacy code book, where most of these refactoring patterns come from. - [Is Typemock too powerful? Will it kill design for testability?](https://osherove.com/blog/2008/1/17/is-typemock-too-powerful-will-it-kill-design-for-testability.html) · osherove.com Roy on whether design for testability equals good design, the point the lesson closes on. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Dependencies, injections, and control](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_65), ch. 3 - [Writing integration tests before refactoring](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_225), ch. 12 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [Entry points and exit points](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_18), ch. 1 - [Constructor injection](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_72), ch. 3 - [E2E/UI isolated tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-10#sigil_toc_id_178), ch. 10 #### The Art of Unit Testing, 2nd ed. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 - [Pros and cons of designing for testability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec3), ch. 11 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 - [Why should I care about testability in my design?](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec1), ch. 11 #### osherove.com - [NDC Video – Michael Feathers – Working Effectively with Legacy Code](https://osherove.com/blog/2009/8/18/ndc-video-michael-feathers-working-effectively-with-legacy-c.html) - [Mock Objects vs. "Inherit & Override"](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html) - [\[Book of the month\] Working effectively with legacy code](https://osherove.com/blog/2005/4/15/book-of-the-month-working-effectively-with-legacy-code.html) - [Dependency Injection - Is it relevant beyond unit testing?](https://osherove.com/blog/2008/1/18/dependency-injection-is-it-relevant-beyond-unit-testing.html) - [Test Driven Validation Logic with Extract & Override](https://osherove.com/blog/2012/5/16/test-driven-validation-logic-with-extract-override.html) - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) - [Refactoring String Calculator with SOLID Principles in Mind - Examples Needed](https://osherove.com/blog/2013/3/6/refactoring-string-calculator-with-solid-principles-in-mind.html) - [Test Reviews Vs. Code Reviews - Some Helpful Tips](https://osherove.com/blog/2007/3/13/test-reviews-vs-code-reviews-some-helpful-tips.html) [Previous lesson Where Do You Start with Legacy Code?](https://courses.osherove.com/courses/legacy-code-hero/where-do-you-start-with-legacy-code/) [Next lesson Instance Delegator Focus](https://courses.osherove.com/courses/legacy-code-hero/instance-delegator-focus/) --- title: "Instance Delegator Focus" url: "https://courses.osherove.com/courses/legacy-code-hero/instance-delegator-focus.md" canonical: "https://courses.osherove.com/courses/legacy-code-hero/instance-delegator-focus/" tags: [] author: "Roy Osherove" description: "Lesson 3 of 5 in Legacy Code Hero (Refactoring), 13:44. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Instance Delegator Focus 1. [Courses](https://courses.osherove.com/#courses) 2. [Legacy Code Hero](https://courses.osherove.com/courses/legacy-code-hero/) 3. Refactoring Lesson 3 of 5 Duration: 13:44 [Watch on YouTube](https://www.youtube.com/watch?v=Ae2OzBGvl7I) In this video Roy Shows specifically, and a bit more slowly, how he uses Instance Delegator to refactor the Manager class in BlogEngine.NET ## In this lesson In BlogEngine.NET, Roy Osherove looks at the static Send method of a manager class, which scans a new post for links and sends trackbacks or pings, and explains why the static class and the blog settings singleton block [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)"). He copies the method into a non-static version, makes the static method forward to a new instance, and extracts virtual methods such as the enable trackback send check so a [testable subclass](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95 "Partial mocks (The Art of Unit Testing, 3rd ed., ch. 4)") can override them. He ends with an exercise: write [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") for when trackbacks and ping backs get sent. ## Transcript 1,834 words [\[00:25\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=25s) So what we have here is the blog engine which we just downloaded from CodePlex. Our exercise for the for the rest of the day will be to write some tests for it. But first I'm going to show some another technique for working with [legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12 "Working with legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") that will help us get some this this thing under test. So because our first exercise will be about writing tests for this without anything like [Typemock](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html "Minimizing unit Test Fragility – 8 features in Typemock Isolator to help (osherove.com)") isolator etc. then we're going to have to learn how to do some extra refactoring stuff. [\[00:59\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=59s) Now, this project surprisingly actually does have some tests, but if we look at them, the tests are unusually simple or even simplistic. A lot of them are [integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)") actually. There's some tests for loading files and making directories. [\[01:31\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=91s) There's some tests for creating posts and some tests actually use IE which means that these tests are integration tests that are using selenium if I'm not mistaken to run an instance of the browser and actually click buttons and links and then check various HTML on the page. So these are not [unit tests](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1 "Defining unit testing, step by step (The Art of Unit Testing, 2nd ed., ch. 1)"), but they are very helpful when you're working with legacy code. [\[02:03\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=123s) For now, we're not going to try to make these tests fast because we're missing all the libraries for running these integration tests. But you can take it as an exercise to try to get these tests to run. But later, not today. What we're going to do is we're going to write some tests for a blog engine manager. Nothing like a core manager class. [\[02:34\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=154s) So this is actually a ping manager class our main interest in this class is the send method. So manager send is going to be our main interest here. So first of all let's talk about what the purpose of this is. Blog engine is a blog engine. You can install it and you can create your own blog. Blogs at the at the bottom of each post of a blog there is a thing there are a couple of sometimes we get automatic links that get posted into there. [\[03:13\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=193s) These are called pings or trackbacks. Pings and trackbacks allow us to create instant conversations when someone else talks about us. And we can create instant conversation in someone else's blog by having a link to their blog in our blog. The the purpose of the send method here is to basically go through the HTML of a new post we just created and search for links to external blogs. And then for each one of them to try to send a ping to a special server out there which collects this information [\[03:51\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=231s) And then that server saves the information and and when that when other blogs ask the server did someone talk about me it will say yes here's the link to whoever talked about you. So it's a way to connect blogs without talking to each other directly. pings and trackbacks only differ by the amount of information they collect if I if I'm not mistaken. But the basic idea is that we have blog settings whether trackback is enabled. We try to send a track back and if we can't send the track back or there's there was a problem where it's not enabled, we send the ping back. [\[04:25\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=265s) So there are two possible [end results](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19 "Exit point types (The Art of Unit Testing, 3rd ed., ch. 1)") from this [unit of work](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points "Unit Testing Entry and Exit Points (osherove.com)"). Okay, one end result is this. Another is this. So our main our main problem is going to be how to test that this was called when it was supposed to with the correct message or that this was called when it was supposed to with the correct message. And there are several things that are going to get in our way when we go through this [\[04:59\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=299s) Because these methods are actually static. We cannot replace the instance of trackback to make sure it was called because send is a static method. Luckily, we can maybe use [extract and override](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html "Mock Objects vs. \"Inherit & Override\" (osherove.com)") to check that something got called. The same here. We also have track back sorry blog settings instance which is a singleton which we will probably need to break as a dependency as well because we don't want to use the real file system. [\[05:30\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=330s) So, we could use extract and override here as well or create an interface with eye settings. But there's another problem. We can't extract and override these things because the class that we're in is a static class. It cannot have non-static methods. So, send is a static method. All the methods here are actually static methods like get track URL from page, get URL from content. [\[06:01\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=361s) Okay, so if we just try to write a simple test for this, what's going to happen is that we're just going to get through all these dependencies and nothing's going to work. So how do we make this class more testable? Well, to get rid of the whole idea of the static so we can extract an override, we can do what's called a a static forwarder. We can keep the static method here, [\[06:35\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=395s) But just a signature. So, what I'm going to do is I'm going to actually create a copy of this cl this method, duplicate it, and have the static removed. and call it send non-static for example. But the problem is that the compiler will say but you're in a static class. So I'm actually going to remove the word static here [\[07:06\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=426s) To make things more testable. The only difference between when I have the word static or not is that the compiler will shout at me if I have non-static methods. So it's kind of useless for us. Now that I can have a non-static method, I'm going to go to the original static method and say just create an instance of new manager and call send non-static with the exact items. [\[07:38\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=458s) So it's a static method that all all that it does is just forwarding the information. And the reason I need the static method is because I don't want to break all the existing callers to the method. Okay, this way the refactoring doesn't break the whole system, but it does allow me to now actually have a manager class that has instance methods. And now I can go to all the private static methods here. What's a private static method? [\[08:09\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=489s) It means it's only going to get used by this class. So it doesn't really matter if it's static or not. And I can make them even protected and virtual. And I can then go and say, okay, I want to break something. Let's go to blog settings, enable trackback send. And instead of actually using a file, I can just extract a method from it and says [\[08:44\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=524s) Enable trackback send and don't make it static. You please make it virtual. And that's it. Now in my test I can actually create a testable manager class that overrides this method and returns whatever we want without using a blog settings configuration file. And the same I can do from anything here. For example, get URLs from content. [\[09:15\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=555s) What does that even mean? It means it goes and it downloads the actual URLs from links inside my content. If I did that, then I'm relying on the web to be present in my tests. It will become an integration test. So I can override this and return whatever I want. The same here like this whole thing remote file. I don't want to have a remote file whatever that means like read from web. [\[09:46\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=586s) Get track back your from page parses using regular expressions. If a regular expression is too complicated to generate inside a test so I will easily find something then maybe it's a dependency as well and finally I can just extract and override these things to extract this into a virtual method etc. So again what I did to make this testable is I removed the static [\[10:16\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=616s) And I made I took the existing static method created a copy of it which is non-static gave it a different name and made the static method just forward to a new instance of my class and called the non-static method. Yes. But in a reality or in a real life case we if we don't have any tests in a legacy code we would rather write some integuation test first before we do this. Yes. In the real world what you would do before you would do this because this is really risky is that you would have at least one or two integration tests that really use the web page and everything to make sure that the existing flow doesn't break and then you can refactor. [\[10:59\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=659s) I wouldn't recommend this kind of refactoring without any integration test but it's worth it. An example is that one time I was sitting with a person I was consulting for them. They had a big legacy system written in C++ and they wanted to add a new attribute to the configuration file. Okay. But they we wanted to do it in a [test-driven](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)") way. So what we did is first we wrote an integration test that actually loads the entire system in memory and with the old configuration file and we checked that the settings were loaded. [\[11:33\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=693s) And then we wrote another test that loads them and then checks for the miss the new setting that was not there yet. And then we made it pass with the attribute. So we actually did a test-driven integration test. It was still worth it. >> >> other questions? Okay. So, what I want you to do is I is as an exercise, I want you to write a couple of tests or more that prove that trackback send gets sent [\[12:10\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=730s) When you have at least one URL that in the content of a post. it get you want to prove also that it gets sent it gets called twice if you have two right because basically let's see there's a loop here so you want to make sure this loop actually works so you want to prove that if you have just one it gets called once if you have two it gets called twice and you also want to prove that if the configuration says that you should not enable track back then you should send a ping back. [\[12:49\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=769s) Okay. You can also prove that if the track back URL is null because there is no trackback URL then it should send a ping back. All these things have a reason. So we should test them. Okay. Okay, so the refactoring we saw was create a static forwarder and then you can use extract and override. Okay, good luck. [\[13:20\]](https://www.youtube.com/watch?v=Ae2OzBGvl7I&t=800s) If there are any questions, just let me know. >> No, you don't have to write the integration test for now. Just write the unit test as if you have integration. ## Related - [Writing integration tests before refactoring](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_225) · The Art of Unit Testing, 3rd ed., ch. 12 The 3rd edition's section on writing integration tests before refactoring, needed before turning the static class into an instance. - [Design goals for testability](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-11#ch11lev1sec2) · The Art of Unit Testing, 2nd ed., ch. 11 The 2nd edition's design goals for testability, relevant to the static class and singleton that block extract and override. - [Tips for Testable code and for testing legacy code](https://osherove.com/blog/2007/6/10/tips-for-testable-code-and-for-testing-legacy-code.html) · osherove.com Roy's consulting notes on getting a hard-to-test business method in legacy code under test. - [Faking static methods in Moq, FakeItEasy and NSubstitute might be closer than imagined](https://osherove.com/blog/2012/7/8/faking-static-methods-in-moq-fakeiteasy-and-nsubstitute-migh.html) · osherove.com On faking static methods directly with proxy frameworks, an alternative to forwarding the static call to an instance. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Partial mocks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95), ch. 4 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Working with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12), ch. 12 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Exit point types](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_19), ch. 1 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 #### The Art of Unit Testing, 2nd ed. - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-1#ch01lev1sec1), ch. 1 #### osherove.com - [Minimizing unit Test Fragility – 8 features in Typemock Isolator to help](https://osherove.com/blog/2009/7/9/minimizing-unit-test-fragility-8-features-in-typemock-isolat.html) - [Unit Testing Entry and Exit Points](https://osherove.com/blog/2020/3/12/unit-testing-entry-points-and-exit-points) - [Mock Objects vs. "Inherit & Override"](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html) [Previous lesson Refactoring Hardcore Skills](https://courses.osherove.com/courses/legacy-code-hero/refactoring-hardcore-skills/) [Next lesson Extract And Override Focus](https://courses.osherove.com/courses/legacy-code-hero/extract-and-override-focus/) --- title: "Extract And Override Focus" url: "https://courses.osherove.com/courses/legacy-code-hero/extract-and-override-focus.md" canonical: "https://courses.osherove.com/courses/legacy-code-hero/extract-and-override-focus/" tags: [] author: "Roy Osherove" description: "Lesson 4 of 5 in Legacy Code Hero (Refactoring), 21:17. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Extract And Override Focus 1. [Courses](https://courses.osherove.com/#courses) 2. [Legacy Code Hero](https://courses.osherove.com/courses/legacy-code-hero/) 3. Refactoring Lesson 4 of 5 Duration: 21:17 [Watch on YouTube](https://www.youtube.com/watch?v=JIPB3peXJSA) In this video Roy Shows how to use, slowly, the [Extract and Override technique](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html "Mock Objects vs. \"Inherit & Override\" (osherove.com)"). ## In this lesson Roy Osherove applies [extract and override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") to a login manager that calls a static logger: the call moves into a protected virtual method with as little logic as possible, which a [testable subclass](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95 "Partial mocks (The Art of Unit Testing, 3rd ed., ch. 4)") overrides to save the message for the test to check. He extends the example to a logger that throws an exception, a call to a static web service and the machine name, then shows extract and override returning [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2 "The difference between mocks and stubs (The Art of Unit Testing, 2nd ed., ch. 4)") objects. He also answers a question on whether extracted methods should be protected or public. ## Transcript 2,922 words [\[00:16\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=16s) Now what we're going to do is we're going to take a look at another technique and it's called [extract and override](https://osherove.com/blog/2012/5/16/test-driven-validation-logic-with-extract-override.html "Test Driven Validation Logic with Extract & Override (osherove.com)"). And this technique is something that I I first learned about this in the book called [working effectively with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226 "Read Michael Feathers’ book on legacy code (The Art of Unit Testing, 3rd ed., ch. 12)"). And now we're kind of jumping into the realm of what happens when you have code that is not very testable and you don't want to use one of the profilerbased frameworks to test it. Okay. How do you refactor the code to be more testable? [\[00:48\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=48s) So here we have the example of login manager with statics. Now the problem here is that I want to test that static logger.Write gets called but I don't have a way to inject the dependency into this. So what I'm going to do is I'm going to refactor the code to make it more testable without changing the functionality. So refactoring the definition is changing code without changing functionality. So making it more testable, more readable, maintainable as long as it does exactly the same as it did before. [\[01:22\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=82s) Nothing more, nothing less. So extract and override is built on top of the idea that you can create a a function, make it virtual, then you can override it by inheriting from the class in your tests. So instead of checking that stat static logger.Write got called, I can do the next best thing. I can extract a method from this control alt m let's call it call logger [\[01:57\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=117s) In the method I'm going to make it protected and virtual it cannot be static that way I can override it in my derived classes in my tests and another another important part is that I want want the method to be to have as less logic as possible. It has to be a simple and stupid method because if it has any logic including the string here in my test, I'm going to be overwriting this method. So there is no way for me to check that the logic inside it is correct. [\[02:32\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=152s) So I'm going to get everything the method needs as a parameter. Ctrl P to extract the parameter. Let's call it text. And now up here we have the method. This is an earlier version of the same method. So we have this and we have call logger and they're connected to each other. So instead of checking that call logger the static logger got called I can check the next best thing that call logger got called and I assume that if this got called then static logger itself got called. [\[03:09\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=189s) That's the next best thing. So the way I [break the dependency](https://osherove.com/blog/2005/8/23/issues-in-breaking-dependencies-for-unit-testing.html "Issues in breaking dependencies for unit testing (osherove.com)") is by creating another layer of indirection in my application. Now in my code I can inherit from the class. So I can create what's called a testable login manager. [\[03:39\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=219s) I like the word testable in the beginning because it tells me that this is not a regular [fake](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2 "Dynamically creating a fake object (The Art of Unit Testing, 2nd ed., ch. 5)") class. This is a version of the real class that I'm testing, but it's a more testable version. And in this testable version, I've broken the dependency to make it more testable. So instead of login manager with statics, this is a testable login manager with statics. [\[04:10\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=250s) I'm just going to change all these change all testable login manager to this. So my test looks like this. In the testable login manager I override the call logger but nothing else. That means that instead of a fake class I actually have just a fake method inside the real class. Everything else around this method behaves just the way it did. But this method itself isn't really calling the static logger. It's just saving the value [\[04:43\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=283s) Just like we do with every other just like we do with every every other fake class. In this case, it's just a fake method. We save the last log message as a public field. Testable login man me manager with statics. I then create it in my test. Instead of the real class, I create the testable class. I call as login. Okay. And then I use string assert to prove that the lm.last message [\[05:15\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=315s) Contains what I'm expecting. And this is the basic idea of extracting override. I can take this a bit further. And you'll see just how powerful this idea really is. First of all, it doesn't force me to introduce a new interface into the system. So it has very little impact and also I can I can break with it almost anything. Let's say that I wanted to prove that not only logger gets called but in a separate requirement I would have if call if the logger throws an exception I wanted to catch it and call the static web service. [\[05:59\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=359s) Okay. So I can take the static web service and I can prove this was called just like I did before. Extract call web service but this time instead of getting the logger exception I don't I don't want to have this logic inside. So let me just make this protected virtual [\[06:30\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=390s) And instead what I'm going to do is I'm going to expect this whole thing as a parameter because if I expect this as a separate parameter and this is a se separate parameter the plus here is actually a piece of logic. I won't have any test to prove that I'm connecting these two things. So instead I'll extract both of these as the expected message. And I don't need the logger exception anymore like this. So now this method is again pretty stupid [\[07:03\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=423s) And all the logic of connecting the message in the current environment machining is in the call to the web service. So now if I wanted to I could have a test that uses testable login manager. So this time if I wanted to simulate an exception, I could put another field public exception to throw equals null. [\[07:34\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=454s) And now I could say something as simple as if to throw is not null then throw whatever it is you need. And now I need to also override the other method call web service and not call the base because then I wouldn't have done anything. I didn't break anything. But here I can just save to let's say last web service [\[08:09\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=489s) Message equals text. Let's make this field. Make it public. That's all I'm doing. And I'm going to assert that the text here is going to be saved to to be saved. So if I write this as a new test, I can say is login. Okay. But the logger throws an exception [\[08:39\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=519s) Then it calls the calls the web service with message and machine name. Okay. So now again I will use the testable login manager with statics and I will say lm to throw equals [\[09:09\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=549s) Exception or whatever I want to simulate. Dude, this is totally a fake section. Then I would still do the same thing is login okay with something and pass [\[09:48\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=588s) Dude. This is complete a fake exception. We can also just contain the current machine name. This is where things begin to get interesting. I can use the current machine name, but I don't want to do this. Plus environment machine name. Why is this not a great idea? Hm. >> Okay. Well, u [\[10:23\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=623s) The machine name will be different somewhere else and and yeah, exactly. The machine name is going to be different on every different machine. Now, that's not a bad idea per se, but the problem is that that means that this test is going to be a different test every time it runs on a different machine. And what we want from a [unit test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") is consistency. So we want to control the machine name so that it always is the same. If you wanted to prove that we can that the machine name local is working etc. [\[10:56\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=656s) We would use an [integration test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25 "Integration tests (The Art of Unit Testing, 3rd ed., ch. 1)"). But for now this is this is the beginning of our solution. We can choose that it contains but if we knew the machine name in the first place we wouldn't need to do this because this is logic inside my test and most likely I'm also repeating production code from here. So this is really important. This could be a big problem. If there is a bug here for example I'm missing space and it's also missing in my production code. I'll never find out because my test is also expecting no space. [\[11:29\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=689s) So, I'd rather have fake exception on machine name. This is much better for me, more readable and expectable. How do I control the machine? Well, I go back to the login manager with statics and I I'll use extract and override again because environment domachine name machine name is just a static property. [\[12:03\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=723s) A property is just a static method. So I can go ahead and extract that again. Extract to a method get machine name. I like methods better than properties. I don't know why. It just feels righter, more more more correct. And again, make it protected virtual. And now I can have full control of the machine name here in the testable version. I can override [\[12:34\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=754s) Get machine name. Now I could say machine name, but that would be a problem. It would be a problem because the reader of my test is going to look and say blah blah blah blah on machine A. Where the hell did machine A come from? So in terms of [readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9 "Readability (The Art of Unit Testing, 3rd ed., ch. 9)"), it's going to look like a magic string. And I want my test to be fully readable. So I don't want my testable and fake classes to have this kind of logic inside them because it hurts readability and I don't want the reader of my test to look in two places to understand what's going on. [\[13:13\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=793s) So instead I will tell it to return machine name. So my test is going to say this lm dot machine name equals machine name. Let's make it play field. That's it. I'm not even going to use a property again because a field is simpler than a property in my tests. [\[13:46\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=826s) So now I can read the test. I can see machine name here and I can see it here. I can see this here and I can see this here and I can fully understand this and I don't have a problem with the the fact that I'm repeating myself in this test because I'd rather repeat myself than hurt the [trust](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134 "How to know you trust a test (The Art of Unit Testing, 3rd ed., ch. 7)") of creating something dynamically that I assert against. I don't want I'd rather not have bugs and this is not a big maintainability issue and it definitely helps to breability. So, as we've seen, extract and override is really powerful and it's actually very simple to do. [\[14:22\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=862s) You just have to get used to doing this. Now, most of the frameworks out there support extract and override. As we've seen, I have an example here with [mock](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76 "Interaction testing, mocks, and stubs (The Art of Unit Testing, 3rd ed., ch. 4)"). If you had such a thing with mock, you could do mock of let's say login manager with virtual method and lm.protected because it method is not public. setup write to log to to accept this and then gets called but we can also say dot [\[14:54\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=894s) What was it we can also tell it to return various things sorry doesn't really matter how to do it right now the the the the the important thing is that this API exists in all of the frameworks so if you wanted to you can use the framework to do it if the method that you we extracted we would make it public then it would work just the same as any other method that we can override. Okay. Personally I hate this API inside the inside the mock because [\[15:32\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=932s) If I wanted to verify it I have to say verifiable here and then I have to verify here. It's kind of a problem. So most of the time I actually use the testable version of something and if there are a lot of methods to override in a testable version then I would use one of the frameworks. Are there any questions about this before we continue? I'll show you another case where this is really helpful. Let's say that we don't have just a static method that let's say that we have a future object. [\[16:06\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=966s) We can use extract and override not just to fake a value but we can actually use it to return a fake object. Let's say that we could if we wanted to inherit from real logger if we could do that we could extract this thing into a virtual method that returns anything that inherits from real logger or i logger in this case. So we can say extract method like get logger and this method [\[16:36\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=996s) Public public static would make it to protected virtual ey logger get logger. By default it returns the real logger but then in our testable version we could return a fake logger. So then anyone who wants to get an instance of a logger actually gets an instance of a fake logger. So extract an override can be used not just to check that the method got called it can also be used to return fake objects and fake values. Another example, [\[17:08\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=1028s) We can use it just like we use it for environment name. We could have used it for configuration settings or for or here we can actually give ourselves two options. The same as here we could either get return here a fake web service or we could fake the whole thing here into a virtual method. So we have two choices of which scope we want to fake. the do we want to return a fake object with an interface or do we just want to prove that some virtual method got called? [\[17:41\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=1061s) The choice is up to us but both of these will be really easy to do. Okay. Now, most of the time I will check that the method got called because it's easier than returning a fake object etc. It makes test more readable. But I still don't have really great ideas on when to use which. Sometimes something feels a bit wrong with just overriding the whole thing. But at the end of the day, it's almost the same. [\[18:11\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=1091s) Should making sure that everything gets sent in with the correct string, etc. Both of these will work just the same. So, you can use this as really, really powerful technique to to work on with a lot of legacy code bases. Another option where I've seen this really helpful is if you have a method with a lot of logic inside it that gets that depends on a lot of decision-m like if this is true then do this if this is true then do this or a method that does a lot of verifications like validations on an email or details and so then you can just extract and override each one of the validations [\[18:47\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=1127s) So that you can set a lot of flags very easily from the test. You can say in the test this validation will return true, this validation will return false, this will return false. Now let's see what happens. So extracting override is really powerful for that kind of stuff as well. >> Yes, >> one question if we have the way and extracting to a protected method we have to we either get the ugly API in case of mock or it's not an issue if you have our own test version of that class. [\[19:19\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=1159s) But if we if we say it's it's not an issue for us and we make it a public message, we can just use it and it's virtual we can we can just use it with a normal way of of using the mocking classes. Yeah. >> Yes. >> So the it really I I see see a big point with a special test version. So that's not the thing. you would say just yeah I was still not decided what I would prefer more just because otherwise we get a lot of classes just for these test versions [\[19:56\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=1196s) And other hand we just have it potentially repeated in the in the test so >> so you're you're still undecided whether you like me keeping things protected or keeping things public. Well, personally, I I I like keeping them protected because I don't want to make too many methods public >> because it kind of spoils the API. On the other hand, yeah, because the point is that this method signifies to me that an external resource got called. [\[20:27\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=1227s) >> Mhm. And if it's public, it's like calling the external resource directly. >> So you would have in that public API one method that eventually calls another public method. Yeah. >> And so it it kind of feels weird in terms of design, >> but so if if it wasn't meant to be public in the first place and it's just to satisfy a compiler, I'm not sure it's a good idea. >> Yeah. Yeah. >> But I could be wrong. [\[20:57\]](https://www.youtube.com/watch?v=JIPB3peXJSA&t=1257s) I still I'm still in dilemmas about this myself. >> Other questions? >> Okay. So continue the exercises from login manager with statics. Okay, don't use any of the frameworks for now. Just use extract and override. ## Related - [Mock Objects vs. "Inherit & Override"](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html) · osherove.com Roy compares mock objects with subclassing and overriding a virtual method, the technique shown slowly in this lesson. - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5) · The Art of Unit Testing, 2nd ed., ch. 3 The 2nd edition's section on variations of refactoring techniques, where it covers extract and override for fake results. - [Partial mocks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95) · The Art of Unit Testing, 3rd ed., ch. 4 The 3rd edition's section on partial mocks, its term for overriding selected methods of the class under test. - [Performance vs. Testability and semi-virtual method calls](https://osherove.com/blog/2005/7/10/performance-vs-testability-and-semi-virtual-method-calls.html) · osherove.com Roy on the cost of making methods virtual for testability, relevant to the protected virtual methods extracted here. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Read Michael Feathers’ book on legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226), ch. 12 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Integration tests](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_25), ch. 1 - [Readability](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-9), ch. 9 - [How to know you trust a test](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-7#sigil_toc_id_134), ch. 7 - [Interaction testing, mocks, and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_76), ch. 4 #### The Art of Unit Testing, 2nd ed. - [The difference between mocks and stubs](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-4#ch04lev1sec2), ch. 4 - [Dynamically creating a fake object](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-5#ch05lev1sec2), ch. 5 #### osherove.com - [Test Driven Validation Logic with Extract & Override](https://osherove.com/blog/2012/5/16/test-driven-validation-logic-with-extract-override.html) - [Issues in breaking dependencies for unit testing](https://osherove.com/blog/2005/8/23/issues-in-breaking-dependencies-for-unit-testing.html) [Previous lesson Instance Delegator Focus](https://courses.osherove.com/courses/legacy-code-hero/instance-delegator-focus/) [Next lesson Extract And Override With Validation Logic](https://courses.osherove.com/courses/legacy-code-hero/extract-and-override-with-validation-logic/) --- title: "Extract And Override With Validation Logic" url: "https://courses.osherove.com/courses/legacy-code-hero/extract-and-override-with-validation-logic.md" canonical: "https://courses.osherove.com/courses/legacy-code-hero/extract-and-override-with-validation-logic/" tags: [] author: "Roy Osherove" description: "Lesson 5 of 5 in Legacy Code Hero (Refactoring), 43:35. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Extract And Override With Validation Logic 1. [Courses](https://courses.osherove.com/#courses) 2. [Legacy Code Hero](https://courses.osherove.com/courses/legacy-code-hero/) 3. Refactoring Lesson 5 of 5 Duration: 43:35 [Watch on YouTube](https://www.youtube.com/watch?v=83h3ge9Ewoo) In this video Roy uses [Extract and Override](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5 "Variations on refactoring techniques (The Art of Unit Testing, 2nd ed., ch. 3)") with a complicated piece of validation logic, showing how you can set easy flags for [unit testing](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17 "Defining unit testing, step by step (The Art of Unit Testing, 3rd ed., ch. 1)") and recreating complicated validation scenarios. ## In this lesson Roy Osherove explains how to test validation code that combines many rules, using a password validator, by testing each rule separately from the logic that combines them. He introduces [extract and override](https://osherove.com/blog/2012/5/16/test-driven-validation-logic-with-extract-override.html "Test Driven Validation Logic with Extract & Override (osherove.com)"), also called the [test specific subclass pattern](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95 "Partial mocks (The Art of Unit Testing, 3rd ed., ch. 4)"), with a testable subclass that overrides the [current time](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec5 "Cross-cutting concerns injection (The Art of Unit Testing, 2nd ed., ch. 7)") so a check does not have to wait seven days. He then writes a validator test first, with flags in a testable subclass that set what each rule returns, and [tests a single rule method directly](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_160 "Avoid testing private or protected methods (The Art of Unit Testing, 3rd ed., ch. 8)") using the [InternalsVisibleTo attribute](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6 "Overcoming the encapsulation problem (The Art of Unit Testing, 2nd ed., ch. 3)"). ## Transcript 4,430 words [\[00:04\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=4s) Hi everyone, my name is Roy Osherove and this is a short video that I'm doing about writing complex logic with complex business rules using [test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27 "Test-driven development (The Art of Unit Testing, 3rd ed., ch. 1)"). The reason I'm doing this video is first of all so that I don't forget and second so that I can show it to students of mine during courses that I teach. And you can find out more about me by going to my blog at icerializable.com. And this is also going to be part of my book which is called [the art of unit testing](https://www.manning.com/books/the-art-of-unit-testing-third-edition "The Art of Unit Testing, Third Edition (The Art of Unit Testing, 3rd ed.)"). [\[00:36\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=36s) And this is an upcoming Manning publication which should be up in about I don't know 5 to 10 years. In any case, you will soon be able to download that book online through manning.com. And if you want to know more or get notifications or even just download the first chapter of the book right now, you can go to the.art ofunitesting.com and download that chapter and get notifications. [\[01:08\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=68s) Now, the the the type of scenario that I'm speaking about right now is a very basic, you know, run-of-the-mill validation constraint logic type of scenario. It's the those kinds of scenarios where you have many rules and you have this big maybe function that checks all these rules and combines them and if depending on some convol logic it returns true or false or does something [\[01:39\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=99s) And a lot of times this is part of validation process in many applications. So the the canonical example that I can think of is password validation function which returns true or false if something is valid or not. And there you know you can have a lot of rules for password validation. For example a minimum number of characters to have digits and so on and so on. Now of course you can use maybe some regular expressions to test these kinds of things. [\[02:10\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=130s) But you know sometimes regular expressions are just for testing the test the text. What if your application needs to test something that is not patternbased? You want to make sure that this is done as well. So you want to make sure that all this logic works. So there are different challenges to testing this kind of function. First of all you need to understand that there are two kinds of tests that you need to to to write for this sort of logic. The first of all is that that you need to test the individual logical constraints. [\[02:45\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=165s) For example, you want to know that if there are maximum number of characters that are exceeded, you want to know that something failed. So you probably would write a separate function and test it out that receives an input and returns true or false whether it passes or not. So you would probably write a different function for each rule and then there is the one layer above which is the logic that uses all these small constraints and combines them to give one single result. [\[03:21\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=201s) So that's the logic that has all the if statements and it says well if there are maximum number of ch characters characters or there aren't any of these and this is not true then do something else. Now the main challenge is that once you know how to test these kinds of constraints is to write in test-driven development. So I'm going to show a demo of how you can actually write in a test-driven manner this kind of logic [\[03:52\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=232s) Using tests that fail first. So here's an example of the validate function on a class and this is this is the hierarchy of how the validate function will work. This is how I want it to look or this is what I have in my mind when I think about it. So you'll notice that in the upper part here the validate function is merely using all these small functions underneath. Now each of one of these methods or functions [\[04:25\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=265s) Is a rule on its own. It does a very simple thing and it has its own logic and this is the complex logic that I would like to test. However, I want to make sure that it's tested and I'm writing it in a test-driven manner. So if I spoke earlier about the two kinds of tests, you'll note that I basically will I'm going to write a test or many tests for the validate function and its logic, but I'm going to write separate tests for the has at least six characters and so on and so on. [\[05:00\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=300s) And the tests here are going to pass or fail independently of the tests here. So even if has at least six characters its tests are going to fail the validate function its own tests might still pass because the logic here still works. So this is basically not very much different than separating dependencies in a regular TDD application TD written application just imagine that this is actually a web service call. [\[05:36\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=336s) So even if the web service doesn't work, I still want to make sure that my interaction with the web service here still works. So this should pass even if this fails. And how do I do this? Well, usually the what happens is that the pattern in the code has to look similar to this. The code uses all these functions and the functions returns true or false. [\[06:06\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=366s) And combining these values use during the test and telling those functions what to return can actually make us test validate separately. So here's an example. We are going to write a test that uses validate but it sets up the the the sub methods here to return the values that the test would like to return. So in our test the scenario would be if the password does not have a digit inside it that is this method returns false [\[06:43\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=403s) And even though all these other methods return true the valid the validate method will return false to the test. Now, this is interesting because if you write test-driven development, you might not actually have this method or this method or this method. You might just have this method to test on, but you still want to make sure that in the next tests, the previous test is still going to to pass. So this will probably make more sense once we get into the code [\[07:19\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=439s) But we are going to go through this scenario and use test-driven de development to write it. Now to understand that we need to understand a a very powerful technique that we're going to use during our testing so that we can actually control these values. I mean there has to be some way to control these values to that our test says well this will return true and this will return false and why do I want to control these values from my test I mean why should my test just give an input to validate that passes this but does not pass this [\[07:56\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=476s) Well the answer is that sometimes to the input to validate by the end of the production code is going to be very very complicated. Just imagine that some of the requirements here may be very very powerful such as the inputs have to be defined in a certain way have to be of a certain size and so on and so on. So I would want to control them even though I don't want to actually run this code. I just want to simulate the fact that has digit returns false. [\[08:28\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=508s) So my test needs to simulate that. And to do that, our test is going to have to create a class that inherits from the class that contains all of this. So if I'm going to actually use some drawing tools here. [\[09:18\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=558s) So the technique is called extract and overwrite. If you're interested in learning more, there's a great book called [working effectively with legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226 "Read Michael Feathers’ book on legacy code (The Art of Unit Testing, 3rd ed., ch. 12)") by [Michael Feathers](https://osherove.com/blog/2009/8/18/ndc-video-michael-feathers-working-effectively-with-legacy-c.html "NDC Video – Michael Feathers – Working Effectively with Legacy Code (osherove.com)") and there he explains this, but this is also called the [test specific subclass pattern](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4 "An object-oriented partial mock example (The Art of Unit Testing, 3rd ed., ch. 4)") if you read the Xunit test patterns book which just came out. So the technique basically says that we're going to create a subclass of the class under test and then overwrite each of these functions [\[09:51\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=591s) And return whatever values we want. So let's see a demo of that and then continue. So, we're in Visual Studio and I just want to show you picture of my son It was born December 28th 2006 and I love him very much. So now he's in the video. In any case, here's my code for the book The Unit Testing and this is everything I have right now. [\[10:25\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=625s) And I'm going to use this solution to show the idea of extraction override and the test specific subclass. So let's add a class that is depending on time so that we can test it and see how we can test it. Let's call it my timebased class. Okay. I'm going to also use a a program called Keyboard Jedi. [\[10:55\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=655s) And the idea about Keyboard Jedi is that it will show any keyboard shortcuts that I'm using inside Visual Studio. I'm also going to use ReSharper so that if you see me doing something like this, you can see that I clicked alt plus enter to show the menu that you're seeing right now. So, this is part of Sharper. I'm just going to optimize the using here. Let's do a public class. [\[11:26\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=686s) And I'm going to write one simple method called public string get [current time](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_64 "Stubbing out time with parameter injection (The Art of Unit Testing, 3rd ed., ch. 3)") to see that it's actually get current time. And well, let's just say that my method is going to be like this. [\[12:02\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=722s) So the method I want to write is a method that maybe is used for backup. And so the method should tell me if a week has passed since the last backup. So let's write a property let's write a field let's say date time. Now the daytime is we're going to use system daytime to say [\[12:33\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=753s) Last backup. And let's create a property. That's the last backup. And let's also do something like public should [\[13:03\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=783s) Back up. Now, let's return false. Well, let's return daytime sub. Let's datetime dot now subtract last backup is [\[13:35\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=815s) In days is bigger than seven. So if more than seven days have passed since the last backup, it should return true. Now how can I test this method? So let's try to write a test for this method. Let's add a new class. Let's call it and since this class is called my timebased class, let's call it my timebased [\[14:06\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=846s) Class tests. Now this is a test class. So it's going to be public and test fixture and let's write a test here. Now in my test I'm going to write three parts. The first part is going to be the method that I'm testing. So should back up now is the name of the [\[14:38\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=878s) Scenario is less than 7 days away returns false is what I'm expecting. Okay. So, how can I test this? So, the first thing I'm going to do is I'm going to refactor the class because I don't want my test to have to wait seven days. So I'm going to actually write a new class here called testable my [\[15:11\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=911s) Timebased class which inherits from my timebased class. Now the reason I'm doing this is so that I can overwrite some stuff. But what do I override first? I'm going to get the current date time and convert that into a method call. So get time now and let's make it [\[15:42\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=942s) Protected and make it virtual. That way we can overwrite that in the class in the testable class. So, what I'm going to do now, I'm just going to override my get time now and say return current time. And what's current time? [\[16:13\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=973s) It's going to be a field called current time. Let's make it public. What else? So now I can use my actual testable timebased class. Testable timebased class backup equals new testable timebased class. Now I'm going to tell backup that the current time [\[16:44\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1004s) Equals new date time. The year is 2000. The month is one. The day is one. That's okay. Now the thing is since this overrides the behavior and actually in the X test patterns book this is a variation of the pattern. It's called [\[17:14\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1034s) Behavior modifying subclass which is pretty smart. What we're going to do is in the test we just told it what the time is. And now we're going to say backup should back up now. [\[18:03\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1083s) Result or let's call it shoot backup now. And I'm going to assert is true on the backup now. So let's see. Here is a test that should actually say well okay this is wrong because my test actually says has to be less than seven days. So has to be is false and the new date time is [\[18:43\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1123s) Okay. Okay. So we have to tell the backup here backup backup last backup equals new date time and let's say 20 1 and 1 and the current time will be 200 and five. So backup now should actually return false. [\[19:15\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1155s) Okay. So current last backup is a standard property. So you can see that in the production code we would actually be using the real date time. But in the tests, we're actually getting getting the the the time that is under the control of our test. So this is called behavior modifying subclass. [\[19:47\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1187s) By overwriting the method, I just change the behavior of the class under test. Therefore, I can override time. I can make time stand still and my test will always run. Let's write the opposite test and see that it actually works. Should back up now more in seven days array returns true. [\[20:19\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1219s) So let's say eight or actually nine. This should be as true. Let's run all of these. And this is actually an addin called testdriven.net that I'm I'm using and I'm running it here. See, two tests have passed. And that's it for now. Let's go back and actually see how we can use this technique [\[20:51\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1251s) To catch complex validation logic. So that was the demo. Let's take a look at what we're going to do now that we know about [extract and override](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html "Mock Objects vs. \"Inherit & Override\" (osherove.com)"). So, we're going to write a password validator class that has all these complex rules and we're going to write a test that uses a validate and it's going to have various virtual methods that we're going to use and we're going to actually override these virtual methods in our test and do in a test-driven manner. [\[21:26\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1286s) So let's see what that looks like right now. So let's write our validator from scratch. So I'm going to actually write a class called validator. But my first test is actually going to be on a method called is valid that takes a password. Now I'm actually testing it on the logical level the one that uses the rules. [\[22:00\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1320s) I'm not testing the actual rules right now. just the fact that the rules are being used correctly in the first and that means that I'm checking checking is valid when rule which is called at least six characters is false then it should return false that means all the other rules return through. [\[22:34\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1354s) So what am I what am I starting with? I'm going to start with the actual testable validator class. Testable validator TV equals new testable validator. And I'm going to make it compile soon, but let's finish the test first. TV. And I'm going to say set all flags to true. [\[23:12\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1392s) Which is my way of saying I'm only testing one rule right now. You'll see that it's a very simple concept. Next, I'm going to say tv flag at least six characters is actually false. So that rules that rule is not passing. All the other ones are. And the next thing I'm going to do, I'm going to say bull is valid equals TV is valid. [\[23:46\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1426s) Some meaningless text as password. Now, this is actually meaningless text as password because I'm not actually testing that it's using the string here. I'm testing that it's calling the underlying rules. The string right now is meaningless. [\[24:16\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1456s) Me some meaningless and I'm asserting that something is false and that would be is valid method. So I'm pretty sure that when you're looking at test right now this seems very very weird to you because there is nothing here that makes much sense but this is the way we are testing the the logic this the way we generate in test driven manner. A testable validator is a validator that allows us to muck around with the behavior. [\[24:47\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1487s) And what are we doing with the behavior? We're saying, well, all rules are going to pass internally besides this rule. Now, when that's true, when all this is true, but this is false, the is valid should actually return false. So, let's make this happen. Let's generate the testable validator class and that's actually going to inherit from a validator class which is not existing right now. [\[25:19\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1519s) So let's create a class and this class is going to be our production code. So this is our test specific subclass and this is the class that we're actually testing. Now let's turn our attention to this interesting method which right now does not do anything. So let's create a field [\[25:50\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1550s) Called flag list characters. And now this method will actually set all the flags. Right now we only have one flag at least six characters is actually actually true. Whenever we add more fields like this, we're going to add a a row here that sets that flag to true. And you can definitely write a simple reflection related method that [\[26:22\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1582s) That loops through all the fields and whatever starts with flag it sets to true. Now the only thing left is to actually implement the is valid method and the is valid method is actually going to be generated on the testable validator class. We are going to move it quickly into [\[26:55\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1615s) A see I'm going to refactor it quickly and say that we're going to move it up into the base class. So this is valid here. So now is valid is part of the validator class and obviously it throws an exception. Now where does this flag take place? [\[27:25\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1645s) Well to do that we need to implement the business rule here. So I know I'm going to do a test driven and the way I'm going to do it is going to say override and I'm going to override a method that doesn't exist yet. And that method is going to be has at least six characters that takes a password string [\[28:09\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1689s) Now the interesting thing is is that I'm going to create the method in the base class and it's going to be generated as a private virtual method. [\[28:41\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1721s) Now what we're going to do is actually say return flag at least six characters. So what do we have so far? We generated a production class that has an isalid method and has an at least six characters method and they both throw an exception. Now we're going to write a test for this one separately. Right now we're testing this method and our test is going to prove that this method is not calling this one. [\[29:13\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1753s) How do we know? Because we are actually testing this class which inherits from this one. And in this class we override the has at least characters method and say that this one returns false. And if this one returns false, then in the production code, this one should not throw an exception. It should just return false. I hope that makes sense. Let's run the test and see what happens. [\[29:48\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1788s) And obviously I get an exception. The method operation is not implemented. So let's make the code pass as as simply as possible. And to do that, let's just say return false. Now, if I run on the test, obviously it will pass, which is weird. So, let's do another test. I'm going to duplicate this code and say, well, is valid when rule is actually true? [\[30:27\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1827s) So this one is actually true and obviously my test will fail. Expected true but was false. I can see here this is why it failed. So let's make the code actually use the production method here. [\[30:58\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1858s) So return has at least six characters. No. Why does that matter? Well, this is a problem. We're going need to need to prove that I'm actually going to have to send in the actual password. But as you can see, the two tests are now passing. So, let's add another rule. Things should get pretty simple from here. The first rule I'm going to add is to say [\[31:36\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1896s) Test is valid. has no spaces is false returns false. So testable. You know what? Let's just make this into a [setup method](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162 "Avoid setup methods (The Art of Unit Testing, 3rd ed., ch. 8)"). [\[32:14\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1934s) We're sharper, refactor, and convert. Oh, never mind that. Let's public setup [\[32:49\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=1969s) And I just say this here I'll do TV and now let's use this TV set all rules to pass. Now TV flag has [\[33:20\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2000s) No spaces equals false, right? And TV is valid. No, doesn't really matter. on valid. So when flag has no spaces false, the TV should turn the testable [\[33:50\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2030s) Validator should turn false. So let's generate this field and flag has no spaces is also true here. And I'm going to override another method. Override bull has no spaces. Return flag has no spaces. Let's generate this method. Create method and base class. [\[34:23\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2063s) Let's run all the tests. Bam. Expected false but was true. Interesting. So what does that mean? Means that all we have to do is add this call here and If you run the test right now, they should all pass. [\[34:57\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2097s) So what happens if we want to test a rule that says one is true and the other is false Well, we obviously don't need to test the other rule the says when this is true because we already have something that says test when everything is true and everything passes. So now what we want to do let's say that we need to add another rule and this one is going to be [\[35:30\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2130s) As valid when rule let's say has the letter A is false has no spaces is [\[36:01\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2161s) False then it should return true. Why? I don't know why. That's just that's that's just a rule that I just made up. So it if it doesn't have the letter A, but it also doesn't have any spaces, it's okay. So let's see. [\[36:32\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2192s) This one is good. Then flag has the letter A is false. Then valid should be true. Let's create a field here. and flag has letter A is true here. Now let's override something else [\[37:22\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2242s) A. Let's implement this. Done. Notice nothing here happens. Now I need to add this test here. I'm running the tests. Obviously this test fails. So now I need to add my new logic here. So the logic that I need to add should be here. [\[38:25\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2305s) So if it has a space but it it h it doesn't have the letter A, it should return true. Return true. I hope I did that right because now it's starting to confuse. Let's see by running the tests. Bam. And they all pass, which is interesting. So now even if I change this to from true to false all my tests should pass even though the logic is horribly flawed. [\[38:57\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2337s) I mean it's not flawed. I mean implementation is not there. Now I can actually let another team write the implementation here. For example some special algorithms team. So let's try to write a test for the method here have at least six characters. And how do I do that? Well, how do I get access to this? Well, I can actually inherit in my class from testable validator. [\[39:30\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2370s) Another thing that I can do is I can actually use the attribute of friend attribute. What was the name of that? Internals visible to attribute. So I can actually say internals visible to attribute as a type of assembly attribute here and just put in the name of an assembly. And if that assembly is a test assembly, [\[40:04\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2404s) It can still look at the protect members or the internal members, I'm sorry. Now, the last thing that I want to do, I'm actually going to move the validator to another file I can actually start testing stuff here. So let's add a test. Now notice the name of the difference in the name. The the difference is has no spaces. [\[40:36\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2436s) That's the method I'm testing. That's the difference. Has a space returns false. So string password equals space. Okay? Because that's the [simplest thing](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html "TDD: 4 questions that will help you create the simplest thing that could possibly work (osherove.com)") I can think of. Validator V equals new validator V. [\[41:07\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2467s) This interesting how do I get access to that? Well, I should say internals visible too. So, I'm actually going to go to V here and say protected internal protected internal and I'm going to say V and you can see that I can see here now here [\[41:39\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2499s) Now if this was a different assembly all I had to do is to put that internals visible too and put the name of my test assembly in there and I would get the same list as it looks has no spaces let's give it the password let's get the result is false has no spaces. If I run my test, [\[42:26\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2546s) Sorry. And of course, this is methane. Let's run my tests again. And of course, my test has failed. And it's failed because has no spaces throws an exception. So all I have to do is say return password contains space. Obviously this could have been much more interesting if the algorithm was more interesting. [\[43:01\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2581s) Bam. All the tests passed. So that way I'm testing the actual algorithms and the logic that uses them separately. Now, by now you should probably be aware that there is it can get more complicated than that. But these are the basic steps that you can do to get this thing rolling. So, thank you for your time. [\[43:31\]](https://www.youtube.com/watch?v=83h3ge9Ewoo&t=2611s) I hope you stop by and check out my book. Thank you very much. ## Related - [Test Driven Validation Logic with Extract & Override](https://osherove.com/blog/2012/5/16/test-driven-validation-logic-with-extract-override.html) · osherove.com Roy test-drives validation logic with extract and override, the same technique used here on the password validator. - [TDD Pattern: Composite Logic Development and Testing](https://osherove.com/blog/2007/9/18/tdd-pattern-composite-logic-development-and-testing.html) · osherove.com Roy's post on testing a Validate method built from smaller rule methods, the composite logic pattern in this lesson. - [TDD Kata 3 - Refactoring](https://osherove.com/tdd-kata-3) · osherove.com A password-verification kata with separate and combined rules, good practice for this lesson's approach. - [Overcoming the encapsulation problem](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec6) · The Art of Unit Testing, 2nd ed., ch. 3 The 2nd edition's section on the encapsulation problem, related to testing a single rule method via InternalsVisibleTo. ### Also linked in this lesson #### The Art of Unit Testing, 3rd ed. - [Partial mocks](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4#sigil_toc_id_95), ch. 4 - [Avoid testing private or protected methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_160), ch. 8 - [Defining unit testing, step by step](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_17), ch. 1 - [Test-driven development](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-1#sigil_toc_id_27), ch. 1 - [The Art of Unit Testing, Third Edition](https://www.manning.com/books/the-art-of-unit-testing-third-edition) - [Read Michael Feathers’ book on legacy code](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-12#sigil_toc_id_226), ch. 12 - [An object-oriented partial mock example](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-4), ch. 4 - [Stubbing out time with parameter injection](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-3#sigil_toc_id_64), ch. 3 - [Avoid setup methods](https://livebook.manning.com/book/the-art-of-unit-testing-third-edition/chapter-8#sigil_toc_id_162), ch. 8 #### The Art of Unit Testing, 2nd ed. - [Cross-cutting concerns injection](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-7#ch07lev1sec5), ch. 7 - [Variations on refactoring techniques](https://livebook.manning.com/book/the-art-of-unit-testing-second-edition/chapter-3#ch03lev1sec5), ch. 3 #### osherove.com - [NDC Video – Michael Feathers – Working Effectively with Legacy Code](https://osherove.com/blog/2009/8/18/ndc-video-michael-feathers-working-effectively-with-legacy-c.html) - [Mock Objects vs. "Inherit & Override"](https://osherove.com/blog/2005/6/16/mock-objects-vs-quotinherit-amp-overridequot.html) - [TDD: 4 questions that will help you create the simplest thing that could possibly work](https://osherove.com/blog/2010/1/6/tdd-4-questions-that-will-help-you-create-the-simplest-thing.html) [Previous lesson Extract And Override Focus](https://courses.osherove.com/courses/legacy-code-hero/extract-and-override-focus/) [Last lesson Back to the course overview](https://courses.osherove.com/courses/legacy-code-hero/) --- title: "Vim Hates You" url: "https://courses.osherove.com/courses/vim-hates-you.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/" tags: [] author: "Roy Osherove" description: "Vim Hates You: 26 lessons, 2 h 16 min. A free video course by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Vim Hates You [Courses](https://courses.osherove.com/#courses) 26 lessons 2 h 16 min 5 sections [Start course](https://courses.osherove.com/courses/vim-hates-you/why-vim/) [Watch on YouTube playlist](https://www.youtube.com/playlist?list=PLHEGKnSLpGpc) ![](https://courses.osherove.com/img/yt/8vwMvLf0bPI.jpg) Teach Vim to love again ## About this course Roy Osherove explains why he thinks [Vim](https://www.youtube.com/watch?v=2BRbyQC9oMw "VIM for Victory • Roy Osherove • GOTO 2013 (YouTube)") is worth learning and then teaches it in short screencasts, starting with opening and saving files, moving around and [changing text](https://osherove.com/blog/2012/5/8/video-vimming-all-about-change.html "[Video] Vimming - All about change (osherove.com)"), modes, copying and pasting, searching and replacing, and setting up a vimrc file. Later sections cover windows and tabs, plugins installed with vim-plug such as Vim Airline, NERDTree, Ctrl-P and ag.vim, and ways to go faster with key mappings, leader keys, registers, the system clipboard, abbreviations and macros. ## Related reading - [Vimming - Natural Selection](https://www.youtube.com/watch?v=aaCGJCJPSjA) · YouTube From the lesson [Understanding Vim Modes and Block Selection Magic](https://courses.osherove.com/courses/vim-hates-you/understanding-vim-modes-and-block-selection-magic/): Roy's Vimming episode on visual-mode selections, the character, line and block selection modes this lesson demonstrates. - [Looking into VIM and ViEmu.](https://osherove.com/blog/2008/3/15/looking-into-vim-and-viemu.html) · osherove.com From the lesson [Useful Vim Commands Reference](https://courses.osherove.com/courses/vim-hates-you/useful-vim-commands-reference/): Roy's post about starting with ViEmu, the tool whose Vim cheat sheet this lesson walks through. - [\[Video\] Vimming - All about change](https://osherove.com/blog/2012/5/8/video-vimming-all-about-change.html) · osherove.com From the lesson [Vim file open save, load, moving, changing and selecting text](https://courses.osherove.com/courses/vim-hates-you/vim-file-open-save-load-moving-changing-and-selecting-text/): A Vimming episode on the change command, which the lesson uses through c, cw and ciw. - [VIM for Victory • Roy Osherove • GOTO 2013](https://www.youtube.com/watch?v=2BRbyQC9oMw) · YouTube From the lesson [Why Vim?](https://courses.osherove.com/courses/vim-hates-you/why-vim/): Roy's GOTO talk making the same case: programmers should be able to use vim and understand how it thinks. ## Curriculum Section 1 ### Get some context 1 lesson · 9 min This section explains why Roy Osherove thinks Vim is worth learning: like regular expressions, it brings a way of thinking about text as motions, commands and operators. It compares edits made in a standard editor with short Vim keystrokes, and mentions Vim bindings in other editors and the comparison with Emacs. 1. [Why Vim? Duration 8:46](https://courses.osherove.com/courses/vim-hates-you/why-vim/) Roy Osherove explains why he thinks Vim is worth learning by comparing it to regular expressions: it brings a different way of thinking about text as motions, commands and operators, such as delete three words back. He compares common edits in a standard editor with Vim keystrokes, such as c, i and a brace to change inside braces, yy and p to duplicate a line, Shift-J to join lines and 3dd to delete three lines. He also notes that Eclipse and Visual Studio have plugins for Vim bindings, and describes Emacs as a powerful editor built on chord-like shortcuts. Section 2 ### Get Somewhat productive in an hour or so 11 lessons · 60 min This section covers opening, saving and quitting files, moving around and changing text, yanking and pasting, and Vim's normal, insert and three selection modes. It sets up a vimrc file with syntax highlighting, line numbers, automatic indentation and color schemes, including one cloned from GitHub. It also covers searching, search and replace with regular expressions, a walk through the ViEmu cheat sheet and vi bindings in Bash and Zsh. 2. [Vim file open save, load, moving, changing and selecting text Duration 7:04](https://courses.osherove.com/courses/vim-hates-you/vim-file-open-save-load-moving-changing-and-selecting-text/) Starting Vim from the command line, Roy writes a hello world file in insert mode, saves it with a colon, w and a file name, and quits with a colon and q, or writes and quits with wq. In what he calls navigation mode he adds lines with o and Shift-O, moves with h, j, k and l and by words with b and w, and undoes with u. He changes text by selecting it with v or Shift-V and pressing c, or with cw and ciw for change word and change in word. 3. [Copying, Pasting and Yanking in Vim Duration 3:30](https://courses.osherove.com/courses/vim-hates-you/copying-pasting-and-yanking-in-vim/) Roy explains that Vim calls copying yanking, done with y, and pastes with p after the cursor or Shift-P before it, whether the yank is a visual selection, several lines selected with Shift-V or a whole line. He shows gp, which leaves the cursor just after the pasted text, yanking a word with a motion (yank in word), copying the whole page with Shift-G, Shift-V, gg and y, and copying columns in Ctrl-V column selection mode. Registers are left for a separate video. 4. [Syntax Highlighting and Numbering in .vimrc file Duration 2:41](https://courses.osherove.com/courses/vim-hates-you/syntax-highlighting-and-numbering-in-vimrc-file/) Working on a new index.html file, Roy turns on Vim's built-in syntax highlighting with syntax enable and line numbers with set number. Because these settings are lost when Vim is reopened, he creates a vimrc file in his home folder with both commands so that they load by default. He ends by pointing ahead to color schemes and the .vim directory. 5. [Basic Searching inside a file in VIM Duration 2:42](https://courses.osherove.com/courses/vim-hates-you/basic-searching-inside-a-file-in-vim/) Roy searches inside a file by typing a forward slash and the text, then pressing n to go to the next match; the search is case sensitive by default and wraps around. He turns on incsearch to highlight the search while typing and hlsearch to highlight all matches, and removes the highlighting with set nohlsearch. A question mark can also be used to search. 6. [Indentation Duration 3:31](https://courses.osherove.com/courses/vim-hates-you/indentation/) Roy indents lines of an HTML file by selecting them with Shift-V and pressing the greater-than sign, de-indents them with the less-than sign, and repeats the last action with the dot key. For automatic indentation he adds filetype indent on to the vimrc file, so that pressing = on a selection makes Vim detect HTML and indent it. He notes that the indentation settings can be overridden in a special vim directory. 7. [Understanding Vim Modes and Block Selection Magic Duration 6:13](https://courses.osherove.com/courses/vim-hates-you/understanding-vim-modes-and-block-selection-magic/) Roy explains that each Vim mode changes how the keyboard behaves: normal or navigation mode is the default, and insert mode can be entered in several ways, such as i, o, Shift-O and Shift-I. He then shows the three selection modes: v for characters, Shift-V for whole lines and Ctrl-V for block (column) selection. In block selection he changes a column of words with c, inserts text before each line with Shift-I and replaces a selection with r, and each change applies to all the selected lines. 8. [Color Schemes Duration 6:20](https://courses.osherove.com/courses/vim-hates-you/color-schemes/) Roy cycles through Vim's built-in color schemes with the color scheme command and Tab, turns on wildmenu to see the options, and makes Zellner the default by adding it to the vimrc file. He points to the Vim Colors site and installs the El Rodeo scheme from GitHub: he creates .vim/colors with mkdir, runs git clone, moves the scheme's colors folder into it and sets the scheme in the vimrc. He also uses Shift-C to change text up to the end of the line. 9. [Basic Search and Replace in a file Duration 4:41](https://courses.osherove.com/courses/vim-hates-you/basic-search-and-replace-in-a-file/) Roy uses the substitute command, typed as a colon, s, the search pattern and the replacement between forward slashes, to replace text on the current line, and applies it to several lines by selecting them with Shift-V first. Only the first match on each line is replaced unless g for global is added at the end. He also shows a range that covers the whole file and the c flag, which asks for confirmation (yes, no, all or quit) at each match. 10. [Search and Replace with Regex Duration 3:20](https://courses.osherove.com/courses/vim-hates-you/search-and-replace-with-regex/) Roy explains that Vim's search and replace is based on regular expressions, and replaces every run of word characters in a file with three underscores, using backslash w for any alphanumeric character, a plus for one or more and the global flag. He points to the vimregex.com site as a reference for character classes and quantifiers. He then replaces all uppercase characters, and after that all runs of non-uppercase characters, with underscores. 11. [Useful Vim Commands Reference Duration 18:06](https://courses.osherove.com/courses/vim-hates-you/useful-vim-commands-reference/) Roy walks through the ViEmu Vim cheat sheet: the colors (green for motions, yellow for commands), the commands in red that end in insert mode, and the keys marked with a dot that need a character argument, such as f and t. He covers motions such as w and W, e, zero and dollar, star and hash, and commands that stay in normal mode, such as r, x and the dot command that repeats the last action. He also shows commands that end in insert mode, such as Shift-C, Shift-A and o, and compares typing Vim commands one key after another with Emacs chords. 12. [Vim Shortcuts in Bash and ZSH Duration 1:36](https://courses.osherove.com/courses/vim-hates-you/vim-shortcuts-in-bash-and-zsh/) Roy shows that Bash and Zsh can use vi key bindings to edit the command line, turned on with set -o vi, which can also go in the shell's rc file. After pressing Escape on a long command line he uses b, cw, dd, p, Shift-P and undo to move, change, delete and paste text. Section 3 ### Divide & Conquer your windows 3 lessons · 8 min This section splits the screen into windows with split and vsplit and moves between them with Ctrl-W, and opens, switches and closes tabs. It then explains that a window is a view into a buffer and that tabs are meant to hold different layouts of windows. 13. [Multiple Windows Duration 3:07](https://courses.osherove.com/courses/vim-hates-you/multiple-windows/) Roy opens a second file next to the current one with vsplit (split adds a horizontal window instead) and moves between windows with Ctrl-W followed by h, j, k or l. He closes a window with q or keeps only the current one with only. On a Mac he recommends turning Caps Lock into Control under the keyboard settings' modifier keys, so that Control is easier to reach. 14. [Vim Tabs Duration 2:10](https://courses.osherove.com/courses/vim-hates-you/vim-tabs/) Roy opens a new tab with tabnew, writes a file in it, and moves to the next tab with gt and to the previous one with g and uppercase T; recent versions also accept Ctrl-Page Up and Page Down. He closes a tab with q, opens a file in a new tab by giving tabnew a file name, or uses tabfind, which searches the Vim path. He adds that some people prefer tabs to windows or buffers. 15. [Tabs as window Layouts Duration 2:25](https://courses.osherove.com/courses/vim-hates-you/tabs-as-window-layouts/) Roy explains that a tab contains windows and each window is a view into a buffer, so the same file can be open in two tabs at once. He argues that tabs are meant as collections of windows used for layout: in one tab he puts the vimrc and a new file side by side with vsplit, adds a third file with split and moves between them with Ctrl-W. He sums up tabs as a way to lay out buffers or to have different views of the same project. Section 4 ### Bring in reinforcements - Plugins 4 lessons · 21 min This section installs the vim-plug plugin manager and uses it to add Vim Airline, the NERDTree file explorer and the Ctrl-P fuzzy file finder. The last lesson adds the ag.vim plugin, which searches for text across files with AG (the Silver Searcher) and shows the results in a quickfix window. 16. [Installing Plugins (Vim plug + Airline) Duration 8:57](https://courses.osherove.com/courses/vim-hates-you/installing-plugins-vim-plug-airline/) Roy points to vimawesome.com for the most used plugins and installs the vim-plug plugin manager by running the curl command from its GitHub page, then declares plugins between its two lines in the vimrc file. He adds Vim Airline and its themes, fixes the word Plugin to Plug, runs PlugInstall, sets laststatus to 2 so that airline is always visible, and picks an airline theme. He also adds comments to the vimrc, which start with a double quote. 17. [NerdTree in Vim Duration 3:39](https://courses.osherove.com/courses/vim-hates-you/nerdtree-in-vim/) Roy installs the NERDTree plugin by copying its line from Vim Awesome into the vimrc file and running the plugin install command. He opens it with NERDTreeToggle, moves between it and the file with Ctrl-W because it is just another window, opens folders and files with o, and shows its help with a question mark, including commands for bookmarks and for creating folders and files. Mapping a key shortcut to the toggle command is left for a later video. 18. [Ctrl-P Duration 2:47](https://courses.osherove.com/courses/vim-hates-you/ctrl-p/) Roy installs the Ctrl-P plugin, a fuzzy file finder, through the vimrc file and PlugInstall, restarting Vim because it reads the vimrc on load. Pressing Ctrl-P lists the files in all subfolders of the current location, and typing part of a file name finds the file so that Enter opens it. He compares this with browsing in NERDTree and finds a combination of the two useful. 19. [Find text in multiple files with AG Duration 6:05](https://courses.osherove.com/courses/vim-hates-you/find-text-in-multiple-files-with-ag/) Roy compares tools for finding text in many files, grep, vimgrep and Ack, and picks AG (the Silver Searcher), which is designed for programmers who search recursively. After installing AG with brew on a Mac, he adds the ag.vim plugin to his vimrc using his leader mappings and installs it. Searching with ag for the word class opens the results in a quickfix window, from which he opens matches in vertical or horizontal splits, moves between windows with Ctrl-W and closes the quickfix window with ccl. Section 5 ### Go Faster 7 lessons · 39 min This section maps keys to actions with the non-recursive noremap commands and a leader key, and adds leader mappings that open, save and source the vimrc file. It also covers registers, the system clipboard through the plus register, abbreviations, and recording and replaying macros. 20. [Mapping keys to actions Duration 8:22](https://courses.osherove.com/courses/vim-hates-you/mapping-keys-to-actions/) Roy maps the down arrow to dd and p and the up arrow to dd, k and Shift-P with the map command, so that the arrows move the current line. He explains that map and its mode versions imap, nmap and vmap are recursive, so later mappings, including those of plugins, can change what they do, and recommends the non-recursive noremap commands. He then adds to his vimrc a noremap that opens NERDTree with Ctrl-N (ending with CR for Enter) and normal-mode noremap versions of the arrow mappings, and loads them with source. 21. [Mapping Leaders in Vim Duration 3:57](https://courses.osherove.com/courses/vim-hates-you/mapping-leaders-in-vim/) Roy explains that the leader is a placeholder key, backslash by default, that many plugins use so that their mappings don't clash with existing key bindings, and that it can be changed with let mapleader. He maps the leader pressed twice to NERDTreeToggle and shows that, before the leader is set in the vimrc, the mapping works with two backslashes. He then sets the leader to comma in the vimrc, so two commas open NERDTree. 22. [Edit and source your .Vimrc faster Duration 4:54](https://courses.osherove.com/courses/vim-hates-you/edit-and-source-your-vimrc-faster/) Roy creates two leader mappings to make changing the vimrc faster: leader ev opens the vimrc in a vertical split through a special variable that always points to the vimrc file, and leader wq writes and quits it and then sources it. He tests them by adding a mapping that opens NERDTree when the leader is pressed twice. He also shows that a mapping removed from the vimrc stays in memory until Vim is restarted. 23. [Understanding Vim Registers Duration 8:37](https://courses.osherove.com/courses/vim-hates-you/understanding-vim-registers/) Roy lists registers with the reg command and pastes from one by typing a double quote, the register name and p, starting with the percent register, which holds the current file name. He shows the double quote register with the last copy or delete, the numbered registers for earlier deletes, the colon register for the last command, named registers such as a that keep a yank, and appending to a register with an uppercase letter. He also covers the black hole, small delete, last search and equals registers, and clearing all registers by removing the viminfo file. 24. [Vim and the System Clipboard Duration 4:57](https://courses.osherove.com/courses/vim-hates-you/vim-and-the-system-clipboard/) Roy checks whether a Vim build supports the system clipboard by looking for the word clipboard in Vim's version output, where grep helps, and a minus sign means it is not supported, as with the built-in Vim on most Macs. He installs MacVim with brew, overriding the system Vim, after which clipboard shows a plus. He then pastes text copied from Hacker News through the plus register (double quote, plus, p) and yanks a line into the system clipboard with double quote, plus, y. 25. [Abbreviations in Vim Duration 2:25](https://courses.osherove.com/courses/vim-hates-you/abbreviations-in-vim/) Roy describes abbreviations as text completions on the fly: he defines one that expands my email into his email address, which could also be kept in the vimrc, and in insert mode it expands as soon as he types a character that is not alphanumeric. He suggests them for long text such as copyright notices and email signatures, or for common spelling mistakes. Unlike a mapping, an abbreviation is only expanded when it is typed outside of another word. 26. [VIm Macros Duration 5:37](https://courses.osherove.com/courses/vim-hates-you/vim-macros/) Roy explains that q and a letter start recording a macro into that register, q again stops it, and the @ sign with the letter plays it back, optionally with a count. To build a numbered list he records a macro into n that yanks and pastes a line and increments its number with Ctrl-A, looks at it with the reg command and runs it 10 times with 10@n. He then pastes the macro into the vimrc as a leader mapping, and notes that a count does not work with that mapping. --- title: "Why Vim?" url: "https://courses.osherove.com/courses/vim-hates-you/why-vim.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/why-vim/" tags: [] author: "Roy Osherove" description: "Lesson 1 of 26 in Vim Hates You (Get some context), 8:46. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Why Vim? 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Get some context Lesson 1 of 26 Duration: 8:46 [Watch on YouTube](https://www.youtube.com/watch?v=8vwMvLf0bPI) ## In this lesson Roy Osherove explains why he thinks [Vim](https://www.youtube.com/watch?v=2BRbyQC9oMw "VIM for Victory • Roy Osherove • GOTO 2013 (YouTube)") is worth learning by comparing it to regular expressions: it brings a different way of thinking about text as motions, commands and operators, such as delete three words back. He compares common edits in a standard editor with Vim keystrokes, such as c, i and a brace to change inside braces, yy and p to duplicate a line, Shift-J to join lines and 3dd to delete three lines. He also notes that Eclipse and [Visual Studio](https://osherove.com/blog/2011/12/14/cool-tool-checking-out-vsvim.html "[Cool Tool] Checking Out VsVim (osherove.com)") have plugins for Vim bindings, and describes Emacs as a powerful editor built on chord-like shortcuts. ## Transcript 1,581 words [\[00:08\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=8s) We get started with learning Vim, I want to explain why I think Vim is such a powerful thing. Why do I even care about it? Why should you learn yet another text editor? So to actually explain that, I want to explain that Vim is not just another text editor. And the way to explain it, I think, is by explaining why regular expressions exist and why they're useful. So let me talk about regular expressions. If you've never used them, regular expressions are really a new language to explain text. [\[00:39\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=39s) They're a way to describe pieces of text in a very meaningful way that is very tur, very simple, and very short. And in that regard once you learn regular expressions and how to talk about text in a form of a regular expression in many fields of working in IT and programming this becomes very useful especially when you're working a lot with text obviously and it's very complicated and it can save you a long a lot of time for things that would be very long to do in a programmatic way. [\[01:13\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=73s) Now, regular expressions are powerful because you can then take the concept and the patterns and then apply them in many other areas. And it's the same thing with Vim. Vim is not just a text editor. But Vim actually brings with it a whole baggage of a different way of thinking about text because the way Vim bindings work is that they allow you to think about text as a different as a set of actions and operators and and motions. Basically in Vim the way that you approach text is that you first navigate through it and the text actually has is separated into logical groupings such as words, sentences, paragraphs and you can navigate between all those three and you can then use operators like move three words back or three sentences or three lines and you can also then apply surgical precision changes like delete three words back. [\[02:06\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=126s) So once you know how to move with specific motions and you know the language that Vim is thinking in, then you can apply really powerful things in and not think in individual characters but think in more logical constructs. For example, delete until the beginning of the page or just like you have page up and page down. Imagine that Vim gives you all this other new type of language to explain how things are built inside text. [\[02:37\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=157s) And in that regard, Vim is a very powerful thing. And because you know Vim bindings once you've learned them, it's important to understand that Vim bindings are so powerful that many editors and many other tools have bindings or plugins that allow you to use Vim bindings inside them when editing text. So for example, if you were working with stuff like Eclipse or [Visual Studio](https://osherove.com/blog/2011/12/14/cool-tool-checking-out-vsvim.html "[Cool Tool] Checking Out VsVim (osherove.com)"), you can have plugins that give you Vim bindings in them. So the knowledge that you have just from working in a Vim in a command line or in a Vim text editor can actually be applied in many other tools, making you giving you the best of both worlds. [\[03:15\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=195s) Both the power of those other IDs and also the power to navigate and change text on the fly very easily instead of moving things one character at a time or one arrow or using the mouse a lot. And as an example, if you if we're comparing the way Vim thinks and the way other text editors think, here's are just a set of a couple of actions to to as an example. If you have an action of [changing text](https://osherove.com/blog/2012/5/8/video-vimming-all-about-change.html "[Video] Vimming - All about change (osherove.com)") inside braces, usually in the standard editor, you would have to like control shift or command shift or alt shift and hit a bunch of arrows repeatedly to move the cursor from one side to the other while selecting and then pressing delete. [\[03:54\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=234s) And many times you would use two or even three fingers on the keyboard at the same time to be able to do this and pressing things repeatedly. The Vim way is usually that there are many different ways to do it and there are it's should be very easy and you should need the least amount of fingers to achieve it. So in Vim you'd press escape and then type C I and then and brace. Basically you could use one finger press escape and then C and then I and then brace. And what happens then is that well technically you can say it's two because having a brace requires a shift. [\[04:30\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=270s) So my mistake but it's still very easy because what I'm telling in the Vimway here is change inside brace. So there's a language here. It's not just a shortcut. Change inside doesn't have to be brace. It could be inside the paragraph or a word or a line. For example, duplicating the current line, you would have to again move arrows and select and shift and all that stuff. But in the Vimway you would press escape because that brings you to a mode called normal mode which I teach in the course and then pressing yp which is basically y [\[05:08\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=308s) Is basically be prepare to paste. Y the second one says the current line. If you do two y's means the current line copy that and p means paste that just below just after what you are. But you can use just a single finger to achieve this. If you want to combine two line two lines to form a single line that's you know you have to move and then press delete or use backspace and you have to be at the end of a line or the beginning of the current line etc. And in Vim you just press escape again you move to normal mode which is navigation. [\[05:40\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=340s) You press shift J no matter where you are on the line and that basically combines the line after you and removes all the ending new line characters in the current line. If you want to delete three lines, you have to control arrow maybe sometimes shift delete delete move down three and then press delete. And in Vim, you don't have to do anything. You if you're in normal mode, you just press three and then dd means delete the current line just like y means yank or copy the current line. [\[06:11\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=371s) And here I'm just saying do that three times. So I just need one finger. So the vim way is about minimal keystrokes to change anything that you want. And it's about learning this language which is made of motions and actions and operators to understand the text you you you want to move through and change kind of like a surgical strike team. And there are usually many ways to do the same thing, but you're really the the way it works is that you're supposed to be only using your hand on the keyboard, not using the mouse, not using even the arrow keys. [\[06:42\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=402s) And if you kind of find yourself doing things with the arrow keys or the mouse, there usually either already is an action or you can configure Vim to create an action which again I teach. And so the Vim bindings and you can see they kind of look scary. All these three different colors like the green and the yellow and the orange there are different type of language constructs and then you apply them together. The green is the motions and the yellow is the commands and you can apply commands into specific motions. So moving so applying the command of delete to all the specific motion of a word or until a specific character. [\[07:19\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=439s) And then operators like how many times do I want to actually achieve that etc etc. And of course you have the insert mode which is just allows you to change things just by typing. But really, insert mode is the mode that you use almost the least because most of the time you navigate and you execute commands instead of typing and pressing backspace etc. in arrow keys. Vim does most of the work for you. One last thing about Vim and Emacs cuz it's the eternal struggle. Emacs is very powerful. I mean there's this sentence Emacs is basically its own operating system. [\[07:52\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=472s) It has so much power and all it's missing is a good text editor. Nice joke. funny, but Emacs really is a very powerful editor and Emacs is really built on really almost chordlike shortcuts that usually use two or three at least three fingers to achieve something and you can do a lot of things and you can customize the hell out of it. So, it's a really powerful editor. You should definitely learn it because you should not limit your worldview to just a single point of view. Always have a critical thinking about the tools that you use and why you're using them. [\[08:25\]](https://www.youtube.com/watch?v=8vwMvLf0bPI&t=505s) So that's kind of the idea. If you want to learn Vim, what you're learning is not the text editor, but a way of thinking about text and a text editor that was built for someone who thinks about text in that way, just like you're using regular expressions. And that will make you much more productive than you are if you're using just a regular text editor. ## Related - [VIM for Victory • Roy Osherove • GOTO 2013](https://www.youtube.com/watch?v=2BRbyQC9oMw) · YouTube Roy's GOTO talk making the same case: programmers should be able to use vim and understand how it thinks. - [\[Cool Tool\] Checking Out VsVim](https://osherove.com/blog/2011/12/14/cool-tool-checking-out-vsvim.html) · osherove.com The lesson mentions Vim bindings for Visual Studio; this post looks at VsVim, which brings Vim keybindings into Visual Studio. - [Looking into VIM and ViEmu.](https://osherove.com/blog/2008/3/15/looking-into-vim-and-viemu.html) · osherove.com Roy's early take on Vim as a keyboard junkie, and on using ViEmu for Vim keys in Visual Studio and Office. ### Also linked in this lesson #### osherove.com - [\[Video\] Vimming - All about change](https://osherove.com/blog/2012/5/8/video-vimming-all-about-change.html) [Next lesson Vim file open save, load, moving, changing and selecting text](https://courses.osherove.com/courses/vim-hates-you/vim-file-open-save-load-moving-changing-and-selecting-text/) --- title: "Vim file open save, load, moving, changing and selecting text" url: "https://courses.osherove.com/courses/vim-hates-you/vim-file-open-save-load-moving-changing-and-selecting-text.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/vim-file-open-save-load-moving-changing-and-selecting-text/" tags: [] author: "Roy Osherove" description: "Lesson 2 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 7:04. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Vim file open save, load, moving, changing and selecting text 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Get Somewhat productive in an hour or so Lesson 2 of 26 Duration: 7:04 [Watch on YouTube](https://www.youtube.com/watch?v=dEsp5YTF6u8) ## In this lesson Starting Vim from the command line, Roy writes a hello world file in insert mode, saves it with a colon, w and a file name, and quits with a colon and q, or writes and quits with wq. In what he calls navigation mode he adds lines with o and Shift-O, moves with h, j, k and l and by words with b and w, and undoes with u. He changes text by selecting it with v or Shift-V and pressing c, or with cw and ciw for change word and change in word. ## Transcript 1,154 words [\[00:12\]](https://www.youtube.com/watch?v=dEsp5YTF6u8&t=12s) Let's start Vim up. We just type vim in the command line. Press enter. And this is the main screen of Vim. And what we're going to do first, we're just going to write a simple hello world text file. And the way that you enter into writing mode in Vim is you type I for insert mode. And now you can see at the bottom here that we're in insert mode and I can type hello world. Now if you want to get out of insert mode and save stuff, you press escape. And now you can see we're no longer in insert mode. [\[00:43\]](https://www.youtube.com/watch?v=dEsp5YTF6u8&t=43s) If we actually want to save the file, we use a special command line mode which is the colon mode. So you type colon. You see at the bottom we can now type a command and there are many multiple commands. many multiple really for example if you want to write you just say w now if I just type w now I'm going to get an error it says oh no file name to save so let's type colon w hello hello world and I'm going to type enter [\[01:15\]](https://www.youtube.com/watch?v=dEsp5YTF6u8&t=75s) And now I can see that there's a file called hello world now let's say I want to quit vim and I want to see the file so how do you quit vim you type colon and Q for quitting. And now what we can see is that if you type ls here, we have a file called hello world. If I show the contents of hello world, you can see that's the content. So let's try to edit the file again. So I'm going to type vim hello world. [\[01:47\]](https://www.youtube.com/watch?v=dEsp5YTF6u8&t=107s) And you can see that I am in the file again. And I can change the text. But how do I change the text? Well, obviously I can press I and then I can move about with the arrows, but that's not the way Vim is really really designed. You see, the way Vim is designed is to kind of give you a surgical like precision attacking your code. So, let's say I want to add a new line. There's a special command for that. So, I'm not in insert mode. I'm not in command mode. I'm in what we call navigation mode or what I call navigation mode. [\[02:20\]](https://www.youtube.com/watch?v=dEsp5YTF6u8&t=140s) And navigation mode also allows for surgical strikes against your code. So if I just want to add a new line below hello world, all I have to do is to say O for a new line below. So O, I want a new line. And here I am in insert mode with a new line. This is the second line. And press escape again. And the way that things work in Vim usually is that you do something something surgical and then you press escape if you want to get back into navigation mode again. [\[02:52\]](https://www.youtube.com/watch?v=dEsp5YTF6u8&t=172s) Let's say I want to add a line just above this line. I don't want to I don't need to go up or down. All I have to do is to say shift O for a line above. Shift O and I'm in insert mode. This is now the now the second line. Now let's say I want to change second line in the third line to the word third. So how do I move down and up? So one way to move down and up is with the J K keys. So J goes down, K goes up. [\[03:24\]](https://www.youtube.com/watch?v=dEsp5YTF6u8&t=204s) J K J K. So I can just move down and up. And I can also move H and L for left and right. Le H and L left and right. J and K. Down and up. But I can also move between words in a in an easier way. So if I want to move a whole word back, I'll say B in navigation mode and I move a whole word back. If I want to move a word forward, I just say W. So I can move back and front. [\[03:55\]](https://www.youtube.com/watch?v=dEsp5YTF6u8&t=235s) Now let's say I want to change this word. I can do it in multiple ways. For example, I can go into what we call selection mode, which is I can press V and then I can move L to the right like this. And now I can press C to change the selection. So I'm going to press C. And now the word I can change it to third. Press escape and I'm done. Now let's say I want to undo that. So I can show you a different way to do it. [\[04:26\]](https://www.youtube.com/watch?v=dEsp5YTF6u8&t=266s) So to undo, you just press U. So I'm going to I just undid that. Let's say I want to change it. There's an easier way to change stuff in Vim. So I can say CW that is change word. So C W will change a word. So now I can say third and press escape again. Let's undo that. And you can see that there is a pattern. Usually the pattern that I use to change a specific word I just say CW. So CW third escape. [\[04:58\]](https://www.youtube.com/watch?v=dEsp5YTF6u8&t=298s) Now I can be in the middle of a word. So I can say change in word. C I W change in word. Third escape. Get undo. Doesn't matter if I'm the beginning or the end. I'm going to say undo and then say changing word third escape. Let's do that to change it to number two. changing word to escape. [\[05:29\]](https://www.youtube.com/watch?v=dEsp5YTF6u8&t=329s) I can select a whole line and change the whole line with not a regular V but a a shift V. So shift V moves into line selection mode. And now when I move up and down I can go up and down like this. And I can change by pressing C and then doing something else in this line. escape. Okay, so that was a kind of a flurry of commands. So, just to repeat, the commands we've learned so far are going up and down with J and K, up and down. [\[06:06\]](https://www.youtube.com/watch?v=dEsp5YTF6u8&t=366s) V for selecting, H and L to move left and right. B to go backwards whole words, W to go forward whole words. Change CW for changing a word from the beginning. here. Escape changing word c i w in the middle of a word and escape for closing. Let's say I want to save the file. I can do command w col w and then write and it will save the file because it already has a file name. [\[06:42\]](https://www.youtube.com/watch?v=dEsp5YTF6u8&t=402s) But let's say I want to quit as well. I can do col wq for write and then quit. And here I am back in the file. I can press cat hello world and this is a new file. So that's the most simple beginning. Next we're going to look at a bit more complicated stuff. ## Related - [vimming - Hello World with vim](https://www.youtube.com/watch?v=eiVnG0lkfF4) · YouTube Roy's short video on the absolute basics: writing text and saving it to a file, as the lesson starts with. - [\[Video\] Vimming - All about change](https://osherove.com/blog/2012/5/8/video-vimming-all-about-change.html) · osherove.com A Vimming episode on the change command, which the lesson uses through c, cw and ciw. - [Vimming - Natural Selection](https://www.youtube.com/watch?v=aaCGJCJPSjA) · YouTube Covers visual-mode selection with v and Shift-V, which the lesson uses before changing text. - [A Casual Introduction to VIM on windows](https://www.youtube.com/watch?v=xJz2Hq-jWxY) · YouTube A relaxed livestreamed walk through Vim basics, a second pass over the opening, editing and saving covered here. [Previous lesson Why Vim?](https://courses.osherove.com/courses/vim-hates-you/why-vim/) [Next lesson Copying, Pasting and Yanking in Vim](https://courses.osherove.com/courses/vim-hates-you/copying-pasting-and-yanking-in-vim/) --- title: "Copying, Pasting and Yanking in Vim" url: "https://courses.osherove.com/courses/vim-hates-you/copying-pasting-and-yanking-in-vim.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/copying-pasting-and-yanking-in-vim/" tags: [] author: "Roy Osherove" description: "Lesson 3 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 3:30. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Copying, Pasting and Yanking in Vim 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Get Somewhat productive in an hour or so Lesson 3 of 26 Duration: 3:30 [Watch on YouTube](https://www.youtube.com/watch?v=rAGEDakYiCI) ## In this lesson Roy explains that Vim calls copying yanking, done with y, and pastes with p after the cursor or Shift-P before it, whether the yank is a visual selection, several lines selected with Shift-V or a whole line. He shows gp, which leaves the cursor just after the pasted text, yanking a word with a motion (yank in word), copying the whole page with Shift-G, Shift-V, gg and y, and copying columns in Ctrl-V column selection mode. Registers are left for a separate video. ## Transcript 559 words [\[00:09\]](https://www.youtube.com/watch?v=rAGEDakYiCI&t=9s) Vim has a different name for copying. It's called yanking. So if you want to copy something, use the letter Y. For example, if I go into [visual mode](https://www.youtube.com/watch?v=aaCGJCJPSjA "Vimming - Natural Selection (YouTube)") with V and I select the current these words and I press yank, then what's going to happen now is that I have this thing in memory. And how do I paste it? I use P or shift P. So P will paste after the cur just after the current cursor. So I'm going to press P. And I see that I have pasted this. [\[00:40\]](https://www.youtube.com/watch?v=rAGEDakYiCI&t=40s) I'm going to press U for undo. But if I press shift P, it inserts this P copy before the cursor. Going to undo that, too. And this works for anything that's selected. So, for example, I'm going to select line shift V. I'm select multiple lines. Press Yank and I'm going press shift P and it pasted those lines just above my current cursor as new lines. [\[01:12\]](https://www.youtube.com/watch?v=rAGEDakYiCI&t=72s) If you want to copy a whole line, just press Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y and this copies the current line in its entirety. Then you can press shiftp right here. You can also press GP which will actually bring the cursor just after inserting the new text. So let's say that I want to yank the current word. Motions work here too. So I'm going to say [\[01:43\]](https://www.youtube.com/watch?v=rAGEDakYiCI&t=103s) Yank in word. This actually copied the word darkness here. I'm going to go down here. I'm going to press GP, which pastes the word darkness and moves the cursor just after it. I'm going to undo it. I'm going to say G, shiftP. I basically get the same thing. It doesn't look like it matters because I had nothing before the cursor in this current line, but basically it will paste the word just before the cursor versus just after and move the cursor to the end of the pasted text, which in this case kind of looks the same. [\[02:21\]](https://www.youtube.com/watch?v=rAGEDakYiCI&t=141s) So that's yanking and pasting. That's what you're going to do most of the time. For example, if you want to copy the whole page, you can press shift G to go to the bottom of the page, shift V to select the whole line and then GG to go up to the beginning of the page and press Y. And now you've pasted the whole page. You've you've copied the whole page. Now you can paste it anywhere with shift P or P just like this. And we've copied the whole thing. [\[02:52\]](https://www.youtube.com/watch?v=rAGEDakYiCI&t=172s) You can of course go to into column selection mode with Ctrl +V. Select all these columns here and press Y. And now they're all pasted. They're all copied. If I go here and I press P, I should have the columns pasted right here. Let's see. I'm going to add more lines here just so we can see what it looks like. And you can see all the columns here. [\[03:22\]](https://www.youtube.com/watch?v=rAGEDakYiCI&t=202s) So that's it for copying and pasting. We still haven't talked about registers, which is a really cool concept. I'm going to cover that in a separate video. ## Related ### Also linked in this lesson #### YouTube - [Vimming - Natural Selection](https://www.youtube.com/watch?v=aaCGJCJPSjA) [Previous lesson Vim file open save, load, moving, changing and selecting text](https://courses.osherove.com/courses/vim-hates-you/vim-file-open-save-load-moving-changing-and-selecting-text/) [Next lesson Syntax Highlighting and Numbering in .vimrc file](https://courses.osherove.com/courses/vim-hates-you/syntax-highlighting-and-numbering-in-vimrc-file/) --- title: "Syntax Highlighting and Numbering in .vimrc file" url: "https://courses.osherove.com/courses/vim-hates-you/syntax-highlighting-and-numbering-in-vimrc-file.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/syntax-highlighting-and-numbering-in-vimrc-file/" tags: [] author: "Roy Osherove" description: "Lesson 4 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 2:41. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Syntax Highlighting and Numbering in .vimrc file 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Get Somewhat productive in an hour or so Lesson 4 of 26 Duration: 2:41 [Watch on YouTube](https://www.youtube.com/watch?v=K2bEwU_i5Hc) ## In this lesson Working on a new index.html file, Roy turns on Vim's built-in syntax highlighting with syntax enable and line numbers with set number. Because these settings are lost when Vim is reopened, he creates a vimrc file in his home folder with both commands so that they load by default. He ends by pointing ahead to color schemes and the .vim directory. ## Transcript 369 words [\[00:07\]](https://www.youtube.com/watch?v=K2bEwU_i5Hc&t=7s) Okay, let's look at some basic configurations we can do to Vim so we can actually make it a bit more usable. Let me create a simple HTML file. And I'm going to say Vim index.html. Even though the file doesn't exist yet, it's going to get created once I save it. I'm just going to paste in some very boilerplate HTML stuff. Press escape and write. So, command write. And what you can see first of all is this. [\[00:38\]](https://www.youtube.com/watch?v=K2bEwU_i5Hc&t=38s) This looks like crap because there's no syntax highlighting. So, we can enable syntax highlighting which is built into Vim for many file types already. I can say command syntax. I can press tab to see that there's a bunch of commands. tab syntax enable. If I type that, we can see that we have syntax outing. That's pretty cool. What about line numbers? Maybe I can set that. So, I can say set command set numbers [\[01:12\]](https://www.youtube.com/watch?v=K2bEwU_i5Hc&t=72s) Number. Sorry, you can see that we have command line numbers in the command line. So I can move up and I can see the various line numbers that I have. And if I press right quick command right quit. So command wq. If I try to open the index html again, you see that we have an issue is that those settings were not saved. So how do we save those settings for later? The answer is that we can create a vimrc file. [\[01:46\]](https://www.youtube.com/watch?v=K2bEwU_i5Hc&t=106s) And the way we do that is we can say vim home that's your home folder and create a vimrc file. So if it doesn't exist yet. So I'm going to create it and I'm going to save it. And we can put the commands we just put in inside the vimrc file. So for example syntax enable that's one command and set number. So that's the other escape command write quit. [\[02:19\]](https://www.youtube.com/watch?v=K2bEwU_i5Hc&t=139s) And if I try to open my index html again, where is it? Vim index.html. We see that we have the default configuration. So that's a good start. Next we're going to see how we can set color schemes and the purpose of the .vim directory, how it relates to plugins and other cool things. [Previous lesson Copying, Pasting and Yanking in Vim](https://courses.osherove.com/courses/vim-hates-you/copying-pasting-and-yanking-in-vim/) [Next lesson Basic Searching inside a file in VIM](https://courses.osherove.com/courses/vim-hates-you/basic-searching-inside-a-file-in-vim/) --- title: "Basic Searching inside a file in VIM" url: "https://courses.osherove.com/courses/vim-hates-you/basic-searching-inside-a-file-in-vim.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/basic-searching-inside-a-file-in-vim/" tags: [] author: "Roy Osherove" description: "Lesson 5 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 2:42. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Basic Searching inside a file in VIM 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Get Somewhat productive in an hour or so Lesson 5 of 26 Duration: 2:42 [Watch on YouTube](https://www.youtube.com/watch?v=sojqXMtNolI) ## In this lesson Roy searches inside a file by typing a forward slash and the text, then pressing n to go to the next match; the search is case sensitive by default and wraps around. He turns on incsearch to highlight the search while typing and hlsearch to highlight all matches, and removes the highlighting with set nohlsearch. A question mark can also be used to search. ## Transcript 407 words [\[00:07\]](https://www.youtube.com/watch?v=sojqXMtNolI&t=7s) Let's talk about searching stuff in Vim. So, the way you search stuff in Vim is that you have two options in the command. Basically, you just type either the forward slash like this and let me just make sure Vim is in focus. So, I type forward slash and now I just type the thing that I'm looking for. So, let's say I'm looking for file type. I just have to type the first part of that. If I press enter, it's going to take me to the first found match. And I can then press N to go to the next match. [\[00:37\]](https://www.youtube.com/watch?v=sojqXMtNolI&t=37s) And obviously, there's only one. Let's say I look I'm looking for the word plug. I'm going to type slash plug. And by default, this is case sensitive, which is usually what you want, but we'll talk about case insensitive in a second. If I type plug now, I'm getting to the first found match. If I press N, I go to the next one and then it basically circles around. There is one helpful option you can set by saying command [\[01:08\]](https://www.youtube.com/watch?v=sojqXMtNolI&t=68s) Set incremental search. So incsearch and this basically highlights the search as I'm typing it. So if I type slash last status, I can see already where it's being found. If I type slashplug, I can see the first highlight. Another option I can set is to say set hlsearch, which means basically highlight all the matches that you find by default. [\[01:40\]](https://www.youtube.com/watch?v=sojqXMtNolI&t=100s) So if I press this, I can see all the matches that were found. Let me search something else. Let's say I'm going to look for set and I can see the first match. But if I type enter, I can see all the matches and I can press N to move between them. Now, how do I remove the highlighting? Because it's going to stay there. I have to type set nohlsearch, which basically removes it. Now, in a later video, I'm going to show how to create custom keyboard bindings so that you can remove the hlsearch just by with the keyboard shortcut. [\[02:20\]](https://www.youtube.com/watch?v=sojqXMtNolI&t=140s) And of course I said that slash is one of the ways to search, but you can also use the question mark. So if I type question mark set, I get the same result basically. And because I don't have hlsearch enabled, then I don't see all the types, all the matches that I [Previous lesson Syntax Highlighting and Numbering in .vimrc file](https://courses.osherove.com/courses/vim-hates-you/syntax-highlighting-and-numbering-in-vimrc-file/) [Next lesson Indentation](https://courses.osherove.com/courses/vim-hates-you/indentation/) --- title: "Indentation" url: "https://courses.osherove.com/courses/vim-hates-you/indentation.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/indentation/" tags: [] author: "Roy Osherove" description: "Lesson 6 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 3:31. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Indentation 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Get Somewhat productive in an hour or so Lesson 6 of 26 Duration: 3:31 [Watch on YouTube](https://www.youtube.com/watch?v=wvmGAA7xN1o) ## In this lesson Roy indents lines of an HTML file by selecting them with Shift-V and pressing the greater-than sign, de-indents them with the less-than sign, and repeats the last action with the dot key. For automatic indentation he adds filetype indent on to the vimrc file, so that pressing = on a selection makes Vim detect HTML and indent it. He notes that the indentation settings can be overridden in a special vim directory. ## Transcript 510 words [\[00:07\]](https://www.youtube.com/watch?v=wvmGAA7xN1o&t=7s) Okay, we still want to get a bit more productive with the HTML for example. So the indentation kind of sucks. So one way to do indentation in Vim is to select the rows you want to indent. So shift V in this case. Let's say all the style and then press shift and the right arrow or the dot. So like this shift and then kind of the larger than sign. And if you want to repeat the command, you can you can actually press dot with nothing and the last thing you did will be repeated again. [\[00:40\]](https://www.youtube.com/watch?v=wvmGAA7xN1o&t=40s) So if I press dot again, you can see that this is repeated. I'm going to press undo once and undo twice. And then if I want to select stuff inside the style, I say I'll say shift V again, select these rows and then shift larger than and then I get the following. And if I want to indent everything inside HTML, I can select this stuff and press shift larger than again. And I want to indent just the body. I can select stuff here and indent, etc., etc. [\[01:13\]](https://www.youtube.com/watch?v=wvmGAA7xN1o&t=73s) So, that's one way to indent things. But I also like to be able to get Vim's help to do all these things. So, I'm going to if I want to de-indent, I can select everything. So, shift V and then GG to go all the way to the beginning of the file and then shift smaller than. So, and I can just repeat this again with a dot. So, let me try this. Shift V then shift G and then unindent and then dot to repeat unindent. [\[01:48\]](https://www.youtube.com/watch?v=wvmGAA7xN1o&t=108s) You can see that this has just repeated the de-indentation of everything. Now there is an auto indentation in Vim. So I can select everything and ideally if I press equals Vim should just detect how to indent HTML. But I don't have indentation turned on and detection in Vim. For that I'm going to have to save the file and then edit the vimrc file. So e home [\[02:20\]](https://www.youtube.com/watch?v=wvmGAA7xN1o&t=140s) Dot vimrc file. And here I need to add one command which is file type indent on this this basically tells Vim to start detecting which file types I'm loading not just for syntax but also for indentation. And if I close Vim write q so right quit and then I in open index html again it doesn't indent automatically. [\[02:55\]](https://www.youtube.com/watch?v=wvmGAA7xN1o&t=175s) I still have to tell it to indent. So I'm going to say shiftv and then shiftg to go all the way down to the file. Now if I press equals, vim detects that this is the HTML and indents things for me. And I can change how it indents things because all of my indentation information can actually be overridden in a special directory which is called the vim directory. We're going to use that for a bit very very soon. So that's how we fix indentation. Let's look at color schemes and other bunch of other useful configuration in the next [Previous lesson Basic Searching inside a file in VIM](https://courses.osherove.com/courses/vim-hates-you/basic-searching-inside-a-file-in-vim/) [Next lesson Understanding Vim Modes and Block Selection Magic](https://courses.osherove.com/courses/vim-hates-you/understanding-vim-modes-and-block-selection-magic/) --- title: "Understanding Vim Modes and Block Selection Magic" url: "https://courses.osherove.com/courses/vim-hates-you/understanding-vim-modes-and-block-selection-magic.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/understanding-vim-modes-and-block-selection-magic/" tags: [] author: "Roy Osherove" description: "Lesson 7 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 6:13. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Understanding Vim Modes and Block Selection Magic 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Get Somewhat productive in an hour or so Lesson 7 of 26 Duration: 6:13 [Watch on YouTube](https://www.youtube.com/watch?v=C_Pe9xlR-WY) ## In this lesson Roy explains that each Vim mode changes how the keyboard behaves: normal or navigation mode is the default, and insert mode can be entered in several ways, such as i, o, Shift-O and Shift-I. He then shows the three selection modes: v for characters, Shift-V for whole lines and Ctrl-V for block (column) selection. In [block selection](https://www.youtube.com/watch?v=aaCGJCJPSjA "Vimming - Natural Selection (YouTube)") he changes a column of words with c, inserts text before each line with Shift-I and replaces a selection with r, and each change applies to all the selected lines. ## Transcript 979 words [\[00:08\]](https://www.youtube.com/watch?v=C_Pe9xlR-WY&t=8s) Let's talk about Vim modes. Vim has different modes and each mode changes how the keyboard behaves. Basically, the default mode that Vim starts at is normal mode or navigation mode. In here, you can use a jk W to move words and and a bunch of other navigation that I'm going to be sharing the shortcuts to in a different video. We can then move from navigation mode to insert mode. So by clicking I am now able to just type. Able to just type. And you can get into insert mode by in many ways. [\[00:42\]](https://www.youtube.com/watch?v=C_Pe9xlR-WY&t=42s) For example, from navigation mode to insert mode at the line above what you are by creating a line just above. You press shift O. And now you're in insert mode in the line above by pressing small O. We are creating a line below and are now in insert mode. By for example pressing shift I we are moving to the beginning of the line and now we are in insert mode. So there are many ways to go into insert mode and saving keystrokes and I'm going to share a whole video about [\[01:21\]](https://www.youtube.com/watch?v=C_Pe9xlR-WY&t=81s) Jumping into insert mode in many different ways. So these are the first two modes simple navigation and insert mode. Then we have selection modes. The simplest selection mode is V. By pressing V, we are now starting to select different files, different text. So I pressed V and now I'm moving and I'm basically just increasing the selection kind of like how you would do with a mouse. So if I have selected a few lines and now for example I want to delete them. I'll just press D [\[01:52\]](https://www.youtube.com/watch?v=C_Pe9xlR-WY&t=112s) And I've removed all the offending text. I'm going to press U to undo that. Note that this does not select the whole line just selects whatever I have currently selected and onwards. And I can of course select using B and W as well using special movement. So www to select one more word, BBB to select backwards, E to select the end of the next word, etc., etc. So the navigation keys [\[02:23\]](https://www.youtube.com/watch?v=C_Pe9xlR-WY&t=143s) Also apply when you're selecting things to increase or decrease the selection. I can then press, for example, C to change the current selection into something else and then press escape, of course, cuz I move from selection mode directly into insert mode by pressing C. I'm going to undo that again. The second selection mode is line selection mode or visual line. And you go into it not by pressing V, but by pressing shift V. So if I press shift V, it doesn't matter if I'm the middle of the line, the whole line is selected. [\[02:57\]](https://www.youtube.com/watch?v=C_Pe9xlR-WY&t=177s) And now I can move up or down to select or deselect different lines. So I have three lines selected. I can press C and change these lines into something else. I'm going to undo. Shift V. Let's delete these four lines. And now I can undo that, too. And I never actually go into insert mode unless I press C or I. In this case, I didn't even select anything. I just press shift C, which is a different shortcut that I'm going to show in a different video. [\[03:29\]](https://www.youtube.com/watch?v=C_Pe9xlR-WY&t=209s) One of the coolest selection modes is [block selection](https://www.youtube.com/watch?v=aaCGJCJPSjA "Vimming - Natural Selection (YouTube)") mode. So, you go into it not by pressing V, not shift V, but by pressing Ctrl +V. So, if I press Ctrl +V here, Ctrl +V, now I can select columns and I can expand the selection. And of course I can change the selection just like by changing here. So I pressed C and now I'm going to type a word and I'm going to press escape or space and then I'm going to press escape. [\[04:03\]](https://www.youtube.com/watch?v=C_Pe9xlR-WY&t=243s) And what you'll see here that all of the bottom lines also got changed into a word. Let me undo that and show again. I'm going to press Ctrl +V select all the is I'm going to press C to change it. I'm going to say was and escape is going to change all the columns to the word was. I can do for example I'm going to go to the beginning by pressing zero. I'm going to select the whole column here. I'm going going to press shift I to insert something right before this. [\[04:37\]](https://www.youtube.com/watch?v=C_Pe9xlR-WY&t=277s) So I'm going to press star space. I'm going to press escape. And this gets applied to all the columns. So I'm going to press undo here for you. So column selection mode is really, really cool and it can really save you a lot of time. I've seen people do demos where they were kind of selecting things like this. I'm in block selection mode. I'm going to select everything here and then I can press the R to replace my current selection. So R and I'm going to press it with space. [\[05:08\]](https://www.youtube.com/watch?v=C_Pe9xlR-WY&t=308s) And immediately everything gets changed into space. Let's do another vis block selection. And I'm going to press Ctrl +V and all these spaces I'm going to press R and replace them with and signs. So it's a very powerful the visual block selection mode is very powerful. So we have the three selection modes which is just visual with V, shift V which is full full line selection and controlV [\[05:39\]](https://www.youtube.com/watch?v=C_Pe9xlR-WY&t=339s) For column selection mode. And then we have insert mode to actually typing. And then we have just movement mode, which is normal mode. So every time you press escape, you go back into normal mode. That's the default. By pressing V or the various V V types, you go into visual selection mode. By pressing I or C or different movements, you go you can go into different insert modes. So that should be enough to get you going and being very productive very very quickly. ## Related - [Vimming - Natural Selection](https://www.youtube.com/watch?v=aaCGJCJPSjA) · YouTube Roy's Vimming episode on visual-mode selections, the character, line and block selection modes this lesson demonstrates. - [\[Video\] Vimming - All about change](https://osherove.com/blog/2012/5/8/video-vimming-all-about-change.html) · osherove.com A Vimming episode on the change command, which the lesson applies to a block selection with c. [Previous lesson Indentation](https://courses.osherove.com/courses/vim-hates-you/indentation/) [Next lesson Color Schemes](https://courses.osherove.com/courses/vim-hates-you/color-schemes/) --- title: "Color Schemes" url: "https://courses.osherove.com/courses/vim-hates-you/color-schemes.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/color-schemes/" tags: [] author: "Roy Osherove" description: "Lesson 8 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 6:20. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Color Schemes 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Get Somewhat productive in an hour or so Lesson 8 of 26 Duration: 6:20 [Watch on YouTube](https://www.youtube.com/watch?v=mR1H9Ijryng) ## In this lesson Roy cycles through Vim's built-in color schemes with the color scheme command and Tab, turns on wildmenu to see the options, and makes Zellner the default by adding it to the vimrc file. He points to the Vim Colors site and installs the El Rodeo scheme from GitHub: he creates .vim/colors with mkdir, runs git clone, moves the scheme's colors folder into it and sets the scheme in the vimrc. He also uses Shift-C to change text up to the end of the line. ## Transcript 800 words [\[00:07\]](https://www.youtube.com/watch?v=mR1H9Ijryng&t=7s) Vim comes bundled with a bunch of power schemes built in. So if I do a vim index html, this is the color scheme that I currently have, but I can change it by typing command colon and typing color scheme. And then I can cycle through different color schemes by pressing tab. So let's do a shift tab and go back one and say morning. This is for example the morning scheme and it kind of hurts my eyes. What others do I have? Let me set another option called wildmenu which gives me a more visual way to see the options I have when I tab through options. [\[00:44\]](https://www.youtube.com/watch?v=mR1H9Ijryng&t=44s) So if I do command set wildmenu and I set that to true basically by just setting set wildmenu I can now do a color scheme and tab through and you can see I can see the options and names. So let's do a Zellner because Zellner sounds awesome. Okay, so that's a Zellner. kind of reminds me of my old days and like an IBM PC XT or something. [\[01:15\]](https://www.youtube.com/watch?v=mR1H9Ijryng&t=75s) Kind of an old game. Anyway, so if we want to save this, all we have to do is by is edit our vimrc page and type here color scheme Zellner. You don't need to use any quotes here. So let's write quit and open Vim index. And this is the default scheme. Now, now if you wanted to install custom, schemes, there's, there's a bunch of them out there. [\[01:50\]](https://www.youtube.com/watch?v=mR1H9Ijryng&t=110s) There are basically thousands and hundred, definitely thousands of schemes out there. One scheme you can there's a great site called Vim Colors where you can kind of see what type and look for the scheme that you really like. if you want to install them. Usually it's as easy as doing a a git clone in a special folder. So, I'm going to show you how to do that. Let's say that we like Monokai. Okay. So, if we like this or let's say something kind of I don't know that looks kind of weird. [\[02:24\]](https://www.youtube.com/watch?v=mR1H9Ijryng&t=144s) Maybe El Dorado. El Rodeo. El Rodeo. Okay. El Rodeo. So if you want to do El Rodeo, we can view it here on GitHub or I can literally copy the link address and go back to my command line. So let me quit this and in my command line I'll go to my home folder cd home. [\[02:56\]](https://www.youtube.com/watch?v=mR1H9Ijryng&t=176s) And in my home, I'm going to create a special folder called Vim. mkdir .vim. And in I'm going to also create another directory called colors. mkdir .vim/colors. Now, this is where color schemes are usually saved. So, let me cd into vim. And all I have to do is do a git clone inside vim, not inside vim colors. and paste in the URL for this color scheme. [\[03:30\]](https://www.youtube.com/watch?v=mR1H9Ijryng&t=210s) And if we look at the what's going on right now, if I say tree, what you'll see is that there is a colors folder inside the El Rodeo color scheme. So, let me move that the folder colors here into my colors folder here. So, let's try to do that. Let's copy or actually move [\[04:06\]](https://www.youtube.com/watch?v=mR1H9Ijryng&t=246s) Move El Rodeo colors to my colors directory. So now if I look what's going on I have my colors directory undervim with the dovim and this is really what's important. Everything else can actually be removed. So I'm gonna remove RM minus RF El Rodeo because that's not needed. So all I have now is just the colors directory with El Rodeo. [\[04:38\]](https://www.youtube.com/watch?v=mR1H9Ijryng&t=278s) Let me copy the name here. And I'm going to change the color scheme by going oneup and changing my vimrc vim. vimrc. By the way, the viminfo just saves cache and late latest actions in Vim. So, it's kind of a Vim last actions file and macros and stuff. So, let me edit the vimrc and change the color scheme here. [\[05:09\]](https://www.youtube.com/watch?v=mR1H9Ijryng&t=309s) And here's a great way to change from the current word onwards. If you if I press shift C, I'm going to change and delete whatever I currently have up until the end of the line from the current location and be in insert mode. So I can basically do a shift C here and press commandV to say El Rodeo escape. Right quit. Now just to make sure you see this again, let me undo. [\[05:41\]](https://www.youtube.com/watch?v=mR1H9Ijryng&t=341s) I come here to this line and I say shift C and paste here. That way I can just very quickly do this surgical work. Right quit. Now let me go back to the city vim course chapter u vim vimrc and I'm going to say vim index.html. And you can see [\[06:11\]](https://www.youtube.com/watch?v=mR1H9Ijryng&t=371s) That El Rodeo is now the default. So that's how you can install different color schemes in Vim. [Previous lesson Understanding Vim Modes and Block Selection Magic](https://courses.osherove.com/courses/vim-hates-you/understanding-vim-modes-and-block-selection-magic/) [Next lesson Basic Search and Replace in a file](https://courses.osherove.com/courses/vim-hates-you/basic-search-and-replace-in-a-file/) --- title: "Basic Search and Replace in a file" url: "https://courses.osherove.com/courses/vim-hates-you/basic-search-and-replace-in-a-file.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/basic-search-and-replace-in-a-file/" tags: [] author: "Roy Osherove" description: "Lesson 9 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 4:41. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Basic Search and Replace in a file 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Get Somewhat productive in an hour or so Lesson 9 of 26 Duration: 4:41 [Watch on YouTube](https://www.youtube.com/watch?v=ZmN-0NtXb4s) ## In this lesson Roy uses the substitute command, typed as a colon, s, the search pattern and the replacement between forward slashes, to replace text on the current line, and applies it to several lines by selecting them with Shift-V first. Only the first match on each line is replaced unless g for global is added at the end. He also shows a range that covers the whole file and the c flag, which asks for confirmation (yes, no, all or quit) at each match. ## Transcript 617 words [\[00:07\]](https://www.youtube.com/watch?v=ZmN-0NtXb4s&t=7s) Let's talk about search and replace inside a file. First the basic commands for searching are acting on the current line. So if I want to replace the letter a in the current line which is the first line. What I want to do is in the command line type colon and then of course I want to substitute. So I want to well I just in my head I say s for search and then forward slash I want you to search for the letter a. [\[00:39\]](https://www.youtube.com/watch?v=ZmN-0NtXb4s&t=39s) So n forward slash that's the search regular expression basically and I want you to replace it with ttt for example and if I just do that what happens is that the letter a changes. However this is only for the current line. So how do I make it so that it applies to two lines? Well there are two ways. Technically before the s you can type in the starting and ending line or the easier way is to move to [visual mode](https://www.youtube.com/watch?v=aaCGJCJPSjA "Vimming - Natural Selection (YouTube)") shift v and let me undo that first shift v [\[01:16\]](https://www.youtube.com/watch?v=ZmN-0NtXb4s&t=76s) And select let's say these three lines and then type colon. And now you'll see at the bottom here is that this is actually indicating the current highlighted search current highlight highlighted text. So I'm going to type again s. So search for a replace it with ttt. Now what happens now is something a bit weird is that it search for all the a's but only the first ones. [\[01:50\]](https://www.youtube.com/watch?v=ZmN-0NtXb4s&t=110s) Let's try that again. This time I'm going to change the letter e. Okay. Just select this and then type search for E and change it to Y Y. And what we we're supposed to see here is that only the first E have been changed. For example, in the first line here. Let's try that again just to make sure. [\[02:21\]](https://www.youtube.com/watch?v=ZmN-0NtXb4s&t=141s) I'm going to press undo. And let's try the same thing with the letter M. Shift V. Search for M. Replace it with UU. And what you'll see is that only the first search in each line is actually being replaced. So if I want more than the first or basically all of the found characters that match the regular expression to actually be replaced, I have to append g for global at the end. [\[02:55\]](https://www.youtube.com/watch?v=ZmN-0NtXb4s&t=175s) So if I select this I type search for in this case m replace it with uu and I'm going to add just this extra slash to say do that globally and that will replace all of the found matches. Now I can also say if I wanted to do this throughout the file, I could technically go GG up, shift V, and then shift G to select all the file and do my search and replace. [\[03:33\]](https://www.youtube.com/watch?v=ZmN-0NtXb4s&t=213s) But there's also a shortcut which is the file name. So I can say the file name that's the range and again substitute all of the E characters with I I I and do that globally. And now this is going to work throughout the file. One last thing is that sometimes you want to get a confirmation [\[04:04\]](https://www.youtube.com/watch?v=ZmN-0NtXb4s&t=244s) For each change. So then you can technically I'm just going to say colon and then go up to repeat and you just add the letter C for confirmation. And now for each match you see at the bottom here you have the ability to say yes or no or all or quit to stop etc or just for this line or until the end of the line. So for us, I can just say yes, yes, no, yes, yes, and all from now on. [\[04:36\]](https://www.youtube.com/watch?v=ZmN-0NtXb4s&t=276s) So that's the simplest way to get that stuff working. ## Related ### Also linked in this lesson #### YouTube - [Vimming - Natural Selection](https://www.youtube.com/watch?v=aaCGJCJPSjA) [Previous lesson Color Schemes](https://courses.osherove.com/courses/vim-hates-you/color-schemes/) [Next lesson Search and Replace with Regex](https://courses.osherove.com/courses/vim-hates-you/search-and-replace-with-regex/) --- title: "Search and Replace with Regex" url: "https://courses.osherove.com/courses/vim-hates-you/search-and-replace-with-regex.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/search-and-replace-with-regex/" tags: [] author: "Roy Osherove" description: "Lesson 10 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 3:20. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Search and Replace with Regex 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Get Somewhat productive in an hour or so Lesson 10 of 26 Duration: 3:20 [Watch on YouTube](https://www.youtube.com/watch?v=f-oFpi6WpYo) ## In this lesson Roy explains that Vim's search and replace is based on regular expressions, and replaces every run of word characters in a file with three underscores, using backslash w for any alphanumeric character, a plus for one or more and the global flag. He points to the vimregex.com site as a reference for character classes and quantifiers. He then replaces all uppercase characters, and after that all runs of non-uppercase characters, with underscores. ## Transcript 457 words [\[00:15\]](https://www.youtube.com/watch?v=f-oFpi6WpYo&t=15s) So, if you thought, you know, kind of basic search and replace was kind of cool, which if you did, you're very, very geeky and nerdy, which is awesome. I appreciate the fact that you're even watching a Vim class. That should definitely give you some props. So if you like that realize that all of the vim search and replace is based on regular expressions. So if you know regular expressions you can be very very powerful. So for example for a regular expression we don't have to have hard-coded values. We can say [\[00:45\]](https://www.youtube.com/watch?v=f-oFpi6WpYo&t=45s) In this file substitute anything in the current reax. So in this case, let's choose everything that is kind of a word character or alpha numeric. So you just put the special back slashw for any alpha numeric character. And of course you can put a slash plus to say it has to be one or more. And now we've finished the search regular expression. And let's replace it with anything that is underscore. [\[01:21\]](https://www.youtube.com/watch?v=f-oFpi6WpYo&t=81s) Let's say three underscores and we'll do this globally of course and if I press enter now we've replaced all of the word characters so it's a pretty powerful thing we have a bunch of regular expressions that you can use in in in Vim and there's a site called Vimregex vimregex.com that you can use to look up it's pretty nice and simple so for example all the whites characters all the digits hex digit etc etc so /w W is what I I really like to use. And of course all the quantifiers. [\[01:52\]](https://www.youtube.com/watch?v=f-oFpi6WpYo&t=112s) So zero or more, at least one or more, etc., etc. And these are like the most common ones that I'll usually use. Also note that you can also say uppercase or or lowerase or non-upercase by having this uppercase and non- lowerase by having this uppercase. So for example, if I want to replace all the uppercase characters in this file, I'll say in this file substitute everything that is [\[02:24\]](https://www.youtube.com/watch?v=f-oFpi6WpYo&t=144s) This would be uppercase but I want to say not uppercase. Well actually let's say uppercase in this case uppercase in this case. Oh I killed me. And replace that with these three underscores and do that globally. If I press enter, replace all of my uppercases. And now I'm going to undo and if I just replace that with an uppercase U, I have done the exact opposite of that. In fact, let me do this. [\[02:56\]](https://www.youtube.com/watch?v=f-oFpi6WpYo&t=176s) Replace it for non-upercase at least one or more replace that with three. So it's not per one or but basically for any sequence of non-uppercase characters. So that's an example of using regular expressions and counters in your Vim substitutions. It's pretty pretty powerful. [Previous lesson Basic Search and Replace in a file](https://courses.osherove.com/courses/vim-hates-you/basic-search-and-replace-in-a-file/) [Next lesson Useful Vim Commands Reference](https://courses.osherove.com/courses/vim-hates-you/useful-vim-commands-reference/) --- title: "Useful Vim Commands Reference" url: "https://courses.osherove.com/courses/vim-hates-you/useful-vim-commands-reference.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/useful-vim-commands-reference/" tags: [] author: "Roy Osherove" description: "Lesson 11 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 18:06. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Useful Vim Commands Reference 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Get Somewhat productive in an hour or so Lesson 11 of 26 Duration: 18:06 [Watch on YouTube](https://www.youtube.com/watch?v=TpgZV9_ktik) ## In this lesson Roy walks through the [ViEmu](https://osherove.com/blog/2008/3/15/looking-into-vim-and-viemu.html "Looking into VIM and ViEmu. (osherove.com)") Vim cheat sheet: the colors (green for motions, yellow for commands), the commands in red that end in insert mode, and the keys marked with a dot that need a character argument, such as f and t. He covers motions such as w and W, e, zero and dollar, star and hash, and commands that stay in normal mode, such as r, x and the dot command that repeats the last action. He also shows commands that end in insert mode, such as Shift-C, Shift-A and o, and compares typing Vim commands one key after another with Emacs chords. ## Transcript 3,008 words [\[00:09\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=9s) Vim shortcuts. I mean, we've we've discussed some of the basic stuff, but I wanted to give you a real overview of all the different types of shortcuts and and commands and the differences between them. And when you start just looking for Vim shortcuts and like basic maps of how they work, there is a bunch of stuff that comes up in Google. One of the best ones is this one which is from the [ViEmu](https://osherove.com/blog/2008/3/15/looking-into-vim-and-viemu.html "Looking into VIM and ViEmu. (osherove.com)") website and it looks very very loaded. But what I thought I'd do in this video is to go through exactly what this contains and the different types of commands and all the information. [\[00:46\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=46s) There's a lot of information here, but if you have this and you understand how to read this, this will be invaluable. You just print it out. You put it on the wall or right next to your keyboard. This will definitely get you a lot of the way there in in making sure that you feel more comfortable in Vim and understand what it is you can and cannot do. But this is too loaded. So what I'm going to do, I'm going to go through each part of this and explain what it is. So first of all, let's just clean things up. [\[01:19\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=79s) One of the things that has nothing to do with everything else is kind of this little cheat sheet right here in the middle of this document. And this talks about the main command line commands, right? The ones that we use to write and save, edit files, etc. It also talks about substitution, help commands, redo, etc. So just out of the out of the gate, make sure that you understand all of these commands and practice them continuously until they kind of feel second nature. [\[01:52\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=112s) The next part is the left part. Left part basically explains the different types of things that are mentioned in this map. And we have, you know, the main three things, the main three modes that we have in Vim are motion, command mode, and basically operations that we have. There's also visual selection, but that's not mentioned here. What's mentioned here are basically what the keys do on the keyboard. So, the keys can either move things around or they can execute commands or they can use operators that are basically [\[02:26\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=146s) Metadata that is provided to a command. And then there's a few extra functions. And then the colors match so that when you see a green something on the keyboard, you know that's a navigation. And yellow is command. So usually what happens in Vim is that you press one of the yellow keys in and then after you'd press a green key. So you would say change word, right? you would say CW because usually commands will take [\[02:59\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=179s) Parameters like you want to change but what it is do you want to change? So we have navigation and we have commands and we connect all these things together. So we have motions, commands and operators and we're going to go a bit deeper very very quickly. If we break down the commands, you'll see that some commands are different than others. For example, some commands, if you look at the full thing, some commands have red letters and some don't. [\[03:30\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=210s) The commands with red red letters are commands that will actually switch you from normal mode into insert mode at the end of the command. So, if I type shift R, that brings me into insert mode. Then I can actually start typing. If I type shift I, it brings me to the beginning of the line and then I'm in insert mode. I can type. If I type shift O, it actually creates a line above, moves to it, and I'm now in insert mode. So these these two types of commands are very important. [\[04:01\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=241s) There's commands that bring you into insert mode and ones that don't. And I'll have a separate slide for that. Then at the bottom left of the chart, you'll see that it mentions that some commands have the dot next to them. And the dot basically means that they require a parameter or a character argument. For example, if you press F, it means you're trying to find something. So L means find the next character and shift F L will find the next L character, etc. [\[04:32\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=272s) Or if you want to move with a green right here to a specific just before a specific something, you say t and then that something and then it will move one character before that something. So everything with a dot for example I want to play a macro I press the add key and then I have to give it the parameter what is the macro location a letter or a number etc etc. And then there's one more thing here at the bottom which is explains words and uppercase words. [\[05:04\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=304s) If you remember we have words navigations in in here you have the word navigation and word basically means you can have uppercase or lowerase. Lowerase word basically means alpha numeric word. So if you have a dot at the end of a car at the end of the word moving pressing small W will move to the dot and then uppercase W or uppercase words basically mean everything that's not whites space. [\[05:35\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=335s) So if you press shift W you're going to move to the next whites space. You're going to move past the dot as well. So that's shift shift W is inclusive and W is uninclusive of non-alpha numeric characters. The only thing that matters for shift W is whites space basically. Let's see. The next thing that's mentioned in the chart is the the numbers here. And then and and I and I highlighted all the c all the keys on the keyboard that have these specific [\[06:12\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=372s) Numbers next to them so that you can see exactly what I mean what they're supposed to mean. For example, in here number three means do this twice so that you affect the whole line. So if I press shift smaller than smaller than at the same time, it will affect the whole line. And here DD has number three here. So it affects the whole line. If I want to copy the whole line, again I have three here. And number one says use X before a yank paste if you want to use a register. [\[06:43\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=403s) And I have a separate video on registers, but basically everything that has a one here will allow me to use a specific register. For example, I want to paste from a specific register or I want to yank to a specific register. And this is how I work with registers. We have number four here, which is basically these special commands that are Z related. They kind of have nothing else to do except Z. And then we have scrolling cursors. This is kind of like minutia, but just I want you just to understand what's going on here. [\[07:19\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=439s) And we have extra commands with GG like go up and shift G to go down. It's not mentioned here. That's I I hid that because it didn't have a u a number associated with it. Now let's talk about motions. Remember that from the main part of the keyboard most of the keys and most of the time you're going to do a lot of motions. That should be your second nature. These are all the motions on the map. And here again we have words and the the we have motions with alpha numeric and we have motions with just everything that's non whitespace. [\[07:55\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=475s) So it only applies to specific words. We have the e which basically leads us to the end of a word or to the end of a lowercase word. We have a two or till which brings us just before a specific character. We have an f which finds one character back. And this one, notice that uppercase in this case brings us back and lowerase moves us forward. Finding a specific character and moving to it. This is finding a specific character and moving right before it. [\[08:28\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=508s) Moving to the top of the screen. These these should be very familiar by now. Moving to the previous word. Moving to the next find when we're searching with the slash or question mark. We can reverse our movements as well. And we have a couple of things we did not talk about yet in this course. So if I press dollar, I go to the end of the line. [\[08:59\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=539s) And if I press POW, I go to the beginning of the line. So, B and E, end of line, beginning of line. And if I press star, I'm actually searching for the next instance of the word. If I press hash, I come to the previous instance of the highlighted word. These are movements that basically allow me to move full full paragraphs, full sentences. [\[09:29\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=569s) And this also depends on how the syntax and the type of syntax in the file. Now, it's kind of hard to remember this. There's a different chart that I found online that that you can get in this URL at the bottom. And what it does is that it kind of shows you the general direction of where movement will take you and how far it will take you for. So, for example, GG will take you all the way up and shift G will take you all the way down. And the bigger the movement, the farther away it will be from the center. [\[10:03\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=603s) So, L, J, K, H will move really, really close to just one character. And then E will move a word and W move award and B will move a word, but back. And then we have shift T versus T before and after. So, there's movement lateral up and down as well. Zero will bring you to the beginning of the line. Dollar will bring you to the end of the line. control pow will bring you to the beginning of the line etc etc. So it's I think it's much easier to memorize things this way. [\[10:36\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=636s) It basically tells you how fast you can navigate with different motions. So it's a very very easy way to remember things. Feels very pragmatic to me but it's still the same thing as this. Now let's talk about commands. We have two types of command like I mentioned and in the chart the two types of commands are red ones and black ones. So regular commands are what I call full circle moves or kind of an air strike move in that you are navigating you have a motion right above the document. [\[11:12\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=672s) You execute a command something changes but you go back into motion. You never go in and start typing in the document. you just say replace all the A's with B's or delete this sentence but you still are in motion mode after that. So you run a command and you go full circle and then basically you just continue moving. And I find that these are this is one of the powers of Vim is that you're able to just kind of look at the document kind of like a through a glass [\[11:46\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=706s) Floor and you say just pull this out, change this, do whatever and without actually touching the document. It's very very fast. But sometimes, and this is another nice thing in Vim, is that you want to use a motion to change things and immediately start typing instead of them or on top or before. So motions plus commands that end in insert mode are also very powerful. And this is a very common theme. For example, [\[12:16\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=736s) These are some of the commands that we can do that are combined of both. These are the full circle moves. So, for example, I can press R and then there's a dot here. So, I can say R I to replace anything that's underneath my cursor with the word I. I can P for paste. I can press shift K to get the help on the current word that I have. I can press U to undo, Y to yank, etc. [\[12:47\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=767s) X to basically sorry small X to just delete the character and shift X to backspace without actually being in insert mode. V basically moves us into selection mode. Equals gives us auto format. This gives us indentation. Dot repeats the last command. So for example, if I did DD and then I move to a different line and I press dot again, it will just repeat DD on that line. So this is a very powerful way of just repeating something very very quickly. [\[13:18\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=798s) It's kind of like a very very short macro that just does the last action you just did in Vim and always remembers only the last action. We can toggle case here. External filter actually allows us to run shell commands as if we're in the command line in in after the colon. So if I type colon exclamation mark, I can basically do ls or or move or anything as if I'm back in the command line and I'll see the output inside the shell and when I press escape or q I'll go back inside vim. [\[13:55\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=835s) Escape moves us into normal mode. So all these things they basically keep us in motion mode right normal mode. And these actions are very powerful because they save us a lot of time and grief. For example, I use this one a lot. Sorry, this one a lot. I'll go to somewhere in the middle of a sentence or just before the end or just the last couple of words and I want to change them. I'll press shift C and then it will basically delete everything from this cursor to the end of the line. [\[14:26\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=866s) Then I can just start typing instead. I don't have to press insert or anything. I'll just I'll be navigation say from this on just split everything just remove whatever you have to the right I just want to type there and C will take a specific movement so if I want to change the in the middle of a sentence I will just want to say change the the next three words I'll just say C3 and I immediately start typing and those words are already deleted if I want to start typing at the end of a sentence but I'm not at the end of it I'm in the middle or at the beginning, I'll just press shift A and I'll start and I'll be in insert mode at the end of the sentence. [\[15:06\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=906s) If I want to just append one character after the character I'm currently on, then I'll just basically press A and S and shift S and S are substitute characters. And I might do a small video on that. I don't really use this too much. Shift I will bas basically bring you into insert mode at the beginning of the current line even if you're in the middle of it. And insert mode will bring you to insert wherever you are currently. Shift O and O opens lines and moves to insert mode above and below the current line that you're in. [\[15:41\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=941s) So these are the commands that will bring you into insert mode from normal mode but also do something on the way. And then we have Z. A lot of people would use ZZ to actually scroll and and and come to a to the middle of the file. Scroll the file to the middle of it. ZT will score to the top and ZZ will center. And some people will just map J and K to also do J and then ZZ because [\[16:12\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=972s) It makes the cursor always in the middle no matter if you're moving up or down. It's pretty awesome. and Z shift Z shift Z will actually save and quit just like saying write quit and ZQ will quit without saving. So that's it for understanding the basic commands and how they work and how they fit with each other. Again, you'll use yellow and then green and usually it's it's a it's a combination. And it the nice thing about Vim, a lot of people say is that if you're using stuff like Emacs, you're writing chords with your hands. [\[16:47\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=1007s) You have to use multiple fingers at the same time. With Vim, usually it's one finger and another. It's like kind kind of like strumming on a guitar. Maybe you do one one string at a time or it's kind of like typing only with two fingers on piano. So I'll find myself usually doing CW. It'll be like ta. And so you'd always feel like da da da da is it kind of feels like a very quick succession of very small commands that are connected to each other. [\[17:18\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=1038s) Kind of like the way that shell like bash works in in Linux and Mac is that there are these small tools and they're connected to each other and one takes the input of another and outputs something that another one takes. So they all work one after the other. So you type them one after the other as one key, one key and then another and then another. While in stuff like Emacs, you have to type all of them together which changes the meaning. So that's it for this section. And don't forget to print it out and and and try to repeat and con consistently look up if you're trying to do something with the mouse or with the arrow keys, stop, look at this, and say, "What? [\[18:00\]](https://www.youtube.com/watch?v=TpgZV9_ktik&t=1080s) How can I do what I'm trying to do using these kinds of commands? ## Related - [Looking into VIM and ViEmu.](https://osherove.com/blog/2008/3/15/looking-into-vim-and-viemu.html) · osherove.com Roy's post about starting with ViEmu, the tool whose Vim cheat sheet this lesson walks through. - [\[Video\] Vimming - All about change](https://osherove.com/blog/2012/5/8/video-vimming-all-about-change.html) · osherove.com Vimming episode on the change command, matching the cheat sheet's commands that end in insert mode, such as Shift-C. - [VIM for Victory • Roy Osherove • GOTO 2013](https://www.youtube.com/watch?v=2BRbyQC9oMw) · YouTube Roy's talk on how Vim thinks, the motions-plus-commands grammar the cheat sheet's colors lay out. [Previous lesson Search and Replace with Regex](https://courses.osherove.com/courses/vim-hates-you/search-and-replace-with-regex/) [Next lesson Vim Shortcuts in Bash and ZSH](https://courses.osherove.com/courses/vim-hates-you/vim-shortcuts-in-bash-and-zsh/) --- title: "Vim Shortcuts in Bash and ZSH" url: "https://courses.osherove.com/courses/vim-hates-you/vim-shortcuts-in-bash-and-zsh.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/vim-shortcuts-in-bash-and-zsh/" tags: [] author: "Roy Osherove" description: "Lesson 12 of 26 in Vim Hates You (Get Somewhat productive in an hour or so), 1:36. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Vim Shortcuts in Bash and ZSH 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Get Somewhat productive in an hour or so Lesson 12 of 26 Duration: 1:36 [Watch on YouTube](https://www.youtube.com/watch?v=J9Yg0aetdVQ) ## In this lesson Roy shows that Bash and Zsh can use vi key bindings to edit the command line, turned on with set -o vi, which can also go in the shell's rc file. After pressing Escape on a long command line he uses b, cw, dd, p, Shift-P and undo to move, change, delete and paste text. ## Transcript 221 words [\[00:06\]](https://www.youtube.com/watch?v=J9Yg0aetdVQ&t=6s) One of the coolest things you can actually do with vi is to understand that its bindings appear almost everywhere. You can even have your bash or zshell in my case to use vim command vim shortcuts. So to set it you would do and this works both in bash or in zshell you would say set minus o and then vi and from this moment on and of course you can put this in your like bash rc file or zshell rc file you you can actually edit your command lines this way. [\[00:39\]](https://www.youtube.com/watch?v=J9Yg0aetdVQ&t=39s) If this is a really long command line and I press escape, let me just show you the shortcuts here. I can actually press B to go back. I can press CW. Let's say CW to change a word here. Changed. I can press escape again. I can press DD to delete the whole line. I can press P to paste the line just above. [\[01:11\]](https://www.youtube.com/watch?v=J9Yg0aetdVQ&t=71s) I can press undo to undo. I can press shift P to paste the line right here and etc etc. So vi is really really useful in many many places and this is just this small tip has changed my life. Well well as far as you can change your life if you're a geek like me when working with command lines. [Previous lesson Useful Vim Commands Reference](https://courses.osherove.com/courses/vim-hates-you/useful-vim-commands-reference/) [Next lesson Multiple Windows](https://courses.osherove.com/courses/vim-hates-you/multiple-windows/) --- title: "Multiple Windows" url: "https://courses.osherove.com/courses/vim-hates-you/multiple-windows.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/multiple-windows/" tags: [] author: "Roy Osherove" description: "Lesson 13 of 26 in Vim Hates You (Divide & Conquer your windows), 3:07. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Multiple Windows 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Divide & Conquer your windows Lesson 13 of 26 Duration: 3:07 [Watch on YouTube](https://www.youtube.com/watch?v=p5gXmwayOxQ) ## In this lesson Roy opens a second file next to the current one with vsplit (split adds a horizontal window instead) and moves between windows with Ctrl-W followed by h, j, k or l. He closes a window with q or keeps only the current one with only. On a Mac he recommends turning Caps Lock into Control under the keyboard settings' modifier keys, so that Control is easier to reach. ## Transcript 446 words [\[00:07\]](https://www.youtube.com/watch?v=p5gXmwayOxQ&t=7s) At this point, we've only been working with a single file each time. So, I want to show you how to work with more than one file at the same time or having more than file one file open and visually visible at the same time. And there are many concepts in Vim such as buffers and windows. I'm going to show how to have multiple windows in Vim. And the command to do this is to either use split or vsplit. So split will have a horizontal window and vsplit will add a vertical window. [\[00:38\]](https://www.youtube.com/watch?v=p5gXmwayOxQ&t=38s) So let's say I want to edit my vimrc on the side here. I'm going to type command here at the bottom vsplit and the name of the file. So home vimrc. And now I have two files. Now the question is how do I move from one file to another? The answer is that you use control W to say window and then you move right or left. [\[01:09\]](https://www.youtube.com/watch?v=p5gXmwayOxQ&t=69s) So you can move right or left either with H or L or J and K if the window is below or above you. So here I'm going to do if I want to move right I'll say control W and then L to move right. WH to move left. And usually it just a very quick syntax. I'm going to try to type it actually very strongly so you can hear how fast it goes [\[01:47\]](https://www.youtube.com/watch?v=p5gXmwayOxQ&t=107s) Now let's say you want to close. You either type Q on the current file like this and you're left with just one of them. Or if I just repeat this, you can type only to remain the only file open. So I'm going to move to the file I want to have open. So now I am in the in this file. I'm going to type command sorry command only. [\[02:17\]](https://www.youtube.com/watch?v=p5gXmwayOxQ&t=137s) This remains the only window. So that way you don't have to close multiple windows if you have more than two open. So those are really really basic steps in working with multiple windows. Now if you're in a Mac just like me and one of the things that is very highly recommended is to transform the caps lock into a control. So it's much easier to type control. And the way you do that is in the keyboard settings under keyboard you can click modifier keys [\[02:48\]](https://www.youtube.com/watch?v=p5gXmwayOxQ&t=168s) And then there either your internal or your external keyboard you change caps lock to also be control and that way it's actually much easier to reach with your left pinky to the control instead of going down. So, it's much easier on your hands that way. [Previous lesson Vim Shortcuts in Bash and ZSH](https://courses.osherove.com/courses/vim-hates-you/vim-shortcuts-in-bash-and-zsh/) [Next lesson Vim Tabs](https://courses.osherove.com/courses/vim-hates-you/vim-tabs/) --- title: "Vim Tabs" url: "https://courses.osherove.com/courses/vim-hates-you/vim-tabs.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/vim-tabs/" tags: [] author: "Roy Osherove" description: "Lesson 14 of 26 in Vim Hates You (Divide & Conquer your windows), 2:10. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Vim Tabs 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Divide & Conquer your windows Lesson 14 of 26 Duration: 2:10 [Watch on YouTube](https://www.youtube.com/watch?v=1t7iOi29REA) ## In this lesson Roy opens a new tab with tabnew, writes a file in it, and moves to the next tab with gt and to the previous one with g and uppercase T; recent versions also accept Ctrl-Page Up and Page Down. He closes a tab with q, opens a file in a new tab by giving tabnew a file name, or uses tabfind, which searches the Vim path. He adds that some people prefer tabs to windows or buffers. ## Transcript 316 words [\[00:06\]](https://www.youtube.com/watch?v=1t7iOi29REA&t=6s) Other than Windows, Vim also has the notion of buffers and and it also has the notion of tabs. So today we're going to look at tabs. And tabs basically mean kind of looks like a tabbed interface. And the way you work with tabs, one of the easiest way to work with it is to go to command mode here at the bottom. Type tab new. And here we have a new tab. It doesn't have any file yet. So technically I could just press I to go to insert mode. This is a file in a new tab. [\[00:37\]](https://www.youtube.com/watch?v=1t7iOi29REA&t=37s) Escape. And then I'm going to write with the file name file 2. And now I have these two tabs. And if I want to move to the next tab or the previous one, I'll do GT to move to the next tab. again GT GT or I can press G and uppercase T to move previous tab. In recent VI versions you can also do control page up and down to move between tabs. [\[01:08\]](https://www.youtube.com/watch?v=1t7iOi29REA&t=68s) And if you want to close a tab, it's very easy. You simply say command sorry go to command and Q for quit. Now our tab is closed. We can also open a tab by just specifying the file name by saying tab new and then file 2. And here I have my tab open. Or I could do a command tab find and then my file 2 and it will search in the vim path which is defined in a vimrc sometimes or in the default vimrc files which I'll explain in different videos. [\[01:52\]](https://www.youtube.com/watch?v=1t7iOi29REA&t=112s) So that's it. Working with tabs is pretty easy. Some people like it way more than working with different window windows or just buffers. A buffer is inside a tab but it's visually different. So you can switch between buffers just by switching between different tabs. [Previous lesson Multiple Windows](https://courses.osherove.com/courses/vim-hates-you/multiple-windows/) [Next lesson Tabs as window Layouts](https://courses.osherove.com/courses/vim-hates-you/tabs-as-window-layouts/) --- title: "Tabs as window Layouts" url: "https://courses.osherove.com/courses/vim-hates-you/tabs-as-window-layouts.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/tabs-as-window-layouts/" tags: [] author: "Roy Osherove" description: "Lesson 15 of 26 in Vim Hates You (Divide & Conquer your windows), 2:25. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Tabs as window Layouts 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Divide & Conquer your windows Lesson 15 of 26 Duration: 2:25 [Watch on YouTube](https://www.youtube.com/watch?v=lrHFrxRkrYo) ## In this lesson Roy explains that a tab contains windows and each window is a view into a buffer, so the same file can be open in two tabs at once. He argues that tabs are meant as collections of windows used for layout: in one tab he puts the vimrc and a new file side by side with vsplit, adds a third file with split and moves between them with Ctrl-W. He sums up tabs as a way to lay out buffers or to have different views of the same project. ## Transcript 376 words [\[00:08\]](https://www.youtube.com/watch?v=lrHFrxRkrYo&t=8s) So now that we've seen windows and tabs, let's understand buffers and the fact that tabs are actually not supposed to be used the way you use tabs today in other IDEs. That is a tab basically can contain a window and a window is just one of them and a window is a view into a specific buffer and you can have multiple windows pointing to the same buffer. In this case, I have one tab that has one window that views the buffer of file 2 and I have another tab with one window that has a view to the vimrc file. [\[00:41\]](https://www.youtube.com/watch?v=lrHFrxRkrYo&t=41s) But technically, I can view both files in two different tabs or the same file in two different tabs. All I have to do is to say e, sorry, let's make this focus. e .vimrc. And now I have the same file open in two tabs. So what's the point of tabs really? If I just go to the next tab, I'm just switching between the file. And the answer is that tabs were really supposed to be a collections of windows or basically used for layout. [\[01:13\]](https://www.youtube.com/watch?v=lrHFrxRkrYo&t=73s) So for example, in this case, I can say that in this tab, I'm editing Vimrc side by side with my new file. So I'm going to do a vsplit and file two. So now in this tab I have these two files and I can move between them with control w and and and right or control w and left that is control wtrl w. I can then further split this. [\[01:43\]](https://www.youtube.com/watch?v=lrHFrxRkrYo&t=103s) For example, in this window right now, I can say split with new file. Another third file that I created. So now I have these three files. I can do control W down, control W right, W left. But this is just the layout of these things. I can switch to my previous tab by saying GT go to next tab. And here I have just one of the files. So I have GT here and I have GT here. And these one of them shows the same file. [\[02:15\]](https://www.youtube.com/watch?v=lrHFrxRkrYo&t=135s) It's just different layouts. So tabs are one way to lay out all your buffers or to have different views of the same project. [Previous lesson Vim Tabs](https://courses.osherove.com/courses/vim-hates-you/vim-tabs/) [Next lesson Installing Plugins (Vim plug + Airline)](https://courses.osherove.com/courses/vim-hates-you/installing-plugins-vim-plug-airline/) --- title: "Installing Plugins (Vim plug + Airline)" url: "https://courses.osherove.com/courses/vim-hates-you/installing-plugins-vim-plug-airline.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/installing-plugins-vim-plug-airline/" tags: [] author: "Roy Osherove" description: "Lesson 16 of 26 in Vim Hates You (Bring in reinforcements - Plugins), 8:57. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Installing Plugins (Vim plug + Airline) 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Bring in reinforcements - Plugins Lesson 16 of 26 Duration: 8:57 [Watch on YouTube](https://www.youtube.com/watch?v=YUKb-4Ekkps) ## In this lesson Roy points to vimawesome.com for the most used plugins and installs the vim-plug plugin manager by running the curl command from its GitHub page, then declares plugins between its two lines in the vimrc file. He adds Vim Airline and its themes, fixes the word Plugin to Plug, runs PlugInstall, sets laststatus to 2 so that airline is always visible, and picks an airline theme. He also adds comments to the vimrc, which start with a double quote. ## Transcript 1,318 words [\[00:09\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=9s) There are many types of plugins that are available for Vim and those plugins really provide a lot of the usefulness that you'll see other people using in screencasts and online is that they usually have a bunch of plugins installed and some of those plugins might be as very wellknown like the NERDTree or surround vim Actually, there's a great site called vimawesome.com where you can really see the list of the most used plugins. I'm going to show a couple of them. But in this specific session, I'm going to show some one that really provides a very visual way to know that you have a new plug-in installed. [\[00:48\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=48s) It's called Vim Airline, which basically gives you a status or tab line for Vim and shows where what's the current active line or column, etc. And technically, you could create your own plugins using Vimscript and sometimes Python, but I'm going to show how to be productive and really get plugins installed and running as quickly as possible. So, the first thing you'll need is a plug-in manager for Vim. Technically, you could install these manually, but plug-in managers exist and they solve the problem in a very, very easy and simple way. [\[01:20\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=80s) And one such plugin is called Vim Plug. And it's a very simple, downto-earth plug-in manager. The way you install it, basically you go to the GitHub repository. It has the instructions there. It even has like a GIF that shows how to use it. And you basically just run the curl command here, which will install it directly from the source control in GitHub onto the vim/.vim/autoload hotfam/autoload folder, which is usually where the plugins that get autoloaded are running. [\[01:54\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=114s) So, we're going to take this command and literally just paste it into our command line which basically just install the plugin. Now, the next thing we need to do is to configure the plugin. And there's a configuration instructions right here. But basically you go to your vimrc and then you add this line at the beginning and then this line right after. And any line in the middle is basically you declaring that you would like a plugin to be installed. [\[02:27\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=147s) And once you have this you go to Vim after it's running and you call the command PlugInstall which installs a plugin. So let me just really quickly just copy this file. We're going to remove most of it. Let's see. We're just going to take this one. This command and I'm going to do a vim vimrc edit. And right now what we're going to do, I'm just going to say [\[02:58\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=178s) Paste the fault the first line and take the last one and paste the last one here. And in between them, I pressed shift O to go one line above. I am just going to choose one. And I I really had a a dilemma which plugin to install first to show you kind of what it's like. So the plugin I chose is called Vim Airline. [\[03:30\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=210s) And the nice thing about it's very visual. It gives a lot of cool features at the beginning. And it's a good way to kind of start looking at how to kind of pimp your Vim in a way. So how do I install Vim airline? Basically, I I just put the vim-airline command here. Now, notice this command is for a different plug plug-in manager. But we're just going to use the word plug instead of plugin. That's the only difference. [\[04:01\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=241s) And it also has two plugins. There's a plugin, the Vim airline, and then it actually has the themes where you can install different themes and how it looks the the command bar. So, let me just copy these two lines and go to my vimrc. Press O to enter a new line and paste. I'm going to delete this line because it's empty. I'm going to press DD to delete the whole line. DD. I'm going to add a new line right after to make things a bit easier to read. [\[04:32\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=272s) And a new line just above with shift O and escape. And I'm going to take these two lines. I'm going to indent them. So I'm going to shift V to select line and then down to select both lines and shift bigger than to move them and indent them a little bit. Now press escape to move out of selection mode and I'm going to do command right quit and I'm going to close Vim and reopen it. [\[05:04\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=304s) Oops. Now there seems to be an issue. We forgot to change the word plugin into plug. So I'm going to press X to delete one character. X and another X to delete the other. I went down and then XX. Notice I'm not even in insert mode. Just like a surgical precision. And again I'm going to escape command right quit. Try to load vimrc again. Now I don't have an issue. Now the plug-in is not yet installed. To install it, I run a command colon [\[05:36\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=336s) PlugInstall. Now I just I'm going to press tab and I'm going to and you see that it autocompletes. That how I know it's actually running. I'm going to press enter. What you'll see is there's a new window in Vim that opens on the left and it shows me the status of installing two plugins. Now they're installed. But if I want to actually run them, I can command write quit. Oops. Now it doesn't let me write cuz this window is kind of read only. [\[06:07\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=367s) So I'm just going to quit all. QA quit all. And if I load up these plugins again, doesn't look like there's a bunch of difference. But watch what happens if I try to split to a vertical window. For example, commandV split. Now you see that there is a command line here at the bottom which shows me a bunch of stuff. But let's say I want to always set that command line to to be visible, not just when I split stuff. [\[06:39\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=399s) Let me just go back to one single window. So I can I'm going to type command only. So only the current window is going to be visible. And I'm going to edit this vimrc file. And I'm going to say set laststatus equals 2, which is the way things are working by default to get the tab always visible. That's what the plug-in needs to hear. By default, it's set to non-visible. Escape. Command right quit. [\[07:10\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=430s) Now, if I open Vimrc, I can see that it's always on. Let's say we want to change the theme. I can actually do a command airline theme. And then if I press tab again, I can see there's a bunch of themes already for airline. So for example, let's use bispin. [\[07:41\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=461s) Okay. So it kind of changes the colors etc. And you can see now that if I move I can see the columns here on the on the right where I am what's the percentage of in the file that I'm in etc etc. If I want I can start putting some comments above and below stuff to make the vimrc file a bit more readable. So shift o to start insert mode the line above and if you want to put a comment just put a double quotes. [\[08:11\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=491s) This is a comment or you know what? I'm going to press CC to change the whole line CC. Double quotes using vim plug. And I'm going to say shift O here. Double quotes. Set airline to always be visible. Okay, I'm going to press O here to enter an empty line here. [\[08:43\]](https://www.youtube.com/watch?v=YUKb-4Ekkps&t=523s) And that's it. That should be enough for now. And I'm going to right quit, open vimrc again. You can see everything is the way it was. [Previous lesson Tabs as window Layouts](https://courses.osherove.com/courses/vim-hates-you/tabs-as-window-layouts/) [Next lesson NerdTree in Vim](https://courses.osherove.com/courses/vim-hates-you/nerdtree-in-vim/) --- title: "NerdTree in Vim" url: "https://courses.osherove.com/courses/vim-hates-you/nerdtree-in-vim.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/nerdtree-in-vim/" tags: [] author: "Roy Osherove" description: "Lesson 17 of 26 in Vim Hates You (Bring in reinforcements - Plugins), 3:39. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # NerdTree in Vim 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Bring in reinforcements - Plugins Lesson 17 of 26 Duration: 3:39 [Watch on YouTube](https://www.youtube.com/watch?v=msgpuC4nEto) ## In this lesson Roy installs the NERDTree plugin by copying its line from Vim Awesome into the vimrc file and running the plugin install command. He opens it with NERDTreeToggle, moves between it and the file with Ctrl-W because it is just another window, opens folders and files with o, and shows its help with a question mark, including commands for bookmarks and for creating folders and files. Mapping a key shortcut to the toggle command is left for a later video. ## Transcript 465 words [\[00:07\]](https://www.youtube.com/watch?v=msgpuC4nEto&t=7s) One of the most powerful useful plugins you'll find for Vim is called NERDTree. And if you go to Vim Awesome, you can see the details for NERDTree here. So, I'm going to show you how to install it and how to basically use it. And this is a it's a longunning plugin. Basically, if we're using one of the install plugins frameworks such as Vim plug in this case, we're just going to copy this, put it in our vimrc file. So, I'm going to go to the command line here and say Vim [\[00:41\]](https://www.youtube.com/watch?v=msgpuC4nEto&t=41s) Vimrc and I'm going to add press O here. Sorry, I'm gonna make sure you're v this is visible to you. Undo. Going to press O. Actually going to press commandV here to paste that. That should be enough for us. Let me command right quit. And this time if we say cd [\[01:11\]](https://www.youtube.com/watch?v=msgpuC4nEto&t=71s) Vim course and we do a vim for let's say basics and hello world and I want to open up the NERDTree. First I have to install it. So, I'm going to say command plugin install at the bottom, which will install the NERDTree. And at this point, I'm going to close this window. [\[01:42\]](https://www.youtube.com/watch?v=msgpuC4nEto&t=102s) And if I want to open the NERDTree window, all I have to do, there are multiple commands to do this, but one of the common ones is command NERDTreeToggle. Where is it? NERDTreeToggle. This one. And this is the window for NERDTree. basically yet another Vim window. And if it's a window, we can just move between those windows with command control W and then J or L. So W L to go right, control WH to go left. [\[02:18\]](https://www.youtube.com/watch?v=msgpuC4nEto&t=138s) And we can of course close it by calling NERDTreeToggle or just command quit because it's just another window. And here we can press O to open the various folders. We can press O to open the file and go directly to start editing it. I can again navigate to the window CRW and open this file instead. Let's go back and open this file. [\[02:51\]](https://www.youtube.com/watch?v=msgpuC4nEto&t=171s) Now you can do much more than that. You can actually have commands that do bookmarks etc. If you want to see all the commands, press question mark. You can see all the commands that you can have inside NERDTree. And that includes actually creating new folders, creating even new files, etc. So, it's a very powerful file explorer which kind of makes it feel like it's a bit easier to work with multiple files this way. [\[03:22\]](https://www.youtube.com/watch?v=msgpuC4nEto&t=202s) Now, you might not want to type NERDTree toggle, etc. And we're going to take a look at mappings and how you can make you can map command key shortcuts to bind to specific commands like NERDTreeToggle in a separate video. [Previous lesson Installing Plugins (Vim plug + Airline)](https://courses.osherove.com/courses/vim-hates-you/installing-plugins-vim-plug-airline/) [Next lesson Ctrl-P](https://courses.osherove.com/courses/vim-hates-you/ctrl-p/) --- title: "Ctrl-P" url: "https://courses.osherove.com/courses/vim-hates-you/ctrl-p.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/ctrl-p/" tags: [] author: "Roy Osherove" description: "Lesson 18 of 26 in Vim Hates You (Bring in reinforcements - Plugins), 2:47. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Ctrl-P 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Bring in reinforcements - Plugins Lesson 18 of 26 Duration: 2:47 [Watch on YouTube](https://www.youtube.com/watch?v=Hp6G43Y-B-M) ## In this lesson Roy installs the Ctrl-P plugin, a fuzzy file finder, through the vimrc file and PlugInstall, restarting Vim because it reads the vimrc on load. Pressing Ctrl-P lists the files in all subfolders of the current location, and typing part of a file name finds the file so that Enter opens it. He compares this with browsing in NERDTree and finds a combination of the two useful. ## Transcript 401 words [\[00:11\]](https://www.youtube.com/watch?v=Hp6G43Y-B-M&t=11s) Another very powerful plugin that I like to have running inside Vim is Ctrl P. And this is basically a fuzzy file finder. Let's say we want to install this and so I can explain what it really is and how to use it. Let's install it again by pasting this inside vimrc. So, let me go back into Vim and let's do a home slash sorry dot vimrc [\[00:42\]](https://www.youtube.com/watch?v=Hp6G43Y-B-M&t=42s) And add this plugin. So, I'm going to put an O here. Paste a new line. Escape. Right quit. Now let me turn on Vim again and do a PlugInstall. And the reason I restarted Vim is because Vim Vim has to read the vimrc file on load. And technically we can also create later like a function that automatically reloads the Vimrc file. But for now I just do it this way and it's it's pretty nice and simple. [\[01:13\]](https://www.youtube.com/watch?v=Hp6G43Y-B-M&t=73s) So now we have Ctrl P installed. So what does it actually do? Let me close this current window. If I press Ctrl P, what you see is that I have this menu inside which actually shows all the default the number of files that I can actually search through. And there's a lot of stuff in there. So, let me instead quit and go into just the current Vim. Just open Vim here directly in this. And if I press Ctrl P, it actually shows all the files in all the subfolders of all the places that I'm in. [\[01:48\]](https://www.youtube.com/watch?v=Hp6G43Y-B-M&t=108s) Let me press escape for a second. Let's open NERDTree so you can see what I'm talking about. NERDTree. Let's see. And this is the NERDTree. And this is all the file the files on my current file system. So instead of searching for something inside NERDTree, I can technically just press Ctrl P and just type part of the file name and it will automatically try to find that file somewhere inside my folder structure. [\[02:23\]](https://www.youtube.com/watch?v=Hp6G43Y-B-M&t=143s) First and you can see that it's the first thing that's already selected. I just press enter and I have the file. Let me switch to hello world. Ctrl P. Hello world. Enter. And I have the file. So it's a very very powerful very very easy to use plugin. And technically you're not you don't even need a tree of files on the left but a combination of both of these is very very useful. [Previous lesson NerdTree in Vim](https://courses.osherove.com/courses/vim-hates-you/nerdtree-in-vim/) [Next lesson Find text in multiple files with AG](https://courses.osherove.com/courses/vim-hates-you/find-text-in-multiple-files-with-ag/) --- title: "Find text in multiple files with AG" url: "https://courses.osherove.com/courses/vim-hates-you/find-text-in-multiple-files-with-ag.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/find-text-in-multiple-files-with-ag/" tags: [] author: "Roy Osherove" description: "Lesson 19 of 26 in Vim Hates You (Bring in reinforcements - Plugins), 6:05. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Find text in multiple files with AG 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Bring in reinforcements - Plugins Lesson 19 of 26 Duration: 6:05 [Watch on YouTube](https://www.youtube.com/watch?v=fn0Et0b-rjY) ## In this lesson Roy compares tools for finding text in many files, grep, vimgrep and Ack, and picks AG (the Silver Searcher), which is designed for programmers who search recursively. After installing AG with brew on a Mac, he adds the ag.vim plugin to his vimrc using his leader mappings and installs it. Searching with ag for the word class opens the results in a quickfix window, from which he opens matches in vertical or horizontal splits, moves between windows with Ctrl-W and closes the quickfix window with ccl. ## Transcript 913 words [\[00:09\]](https://www.youtube.com/watch?v=fn0Et0b-rjY&t=9s) One of the things that always for frustrated me the most about working inside Vim is trying to find stuff inside multiple multiple files. So if we have this following directory structure and I want to find all the instances of class then I don't have a lot of good choices that are easy really easy to remember. One one tool that everyone uses is grep and there's a thing called vimgrep inside vim but the syntax for it is really hard to remember and it's not very comfortable. [\[00:40\]](https://www.youtube.com/watch?v=fn0Et0b-rjY&t=40s) Then there's AC Ack, which is another tool that's also very common and we could technically use that. But then there's this third tool that I learned about called AG or the silver searcher. And this is the website for this tool. The silver searcher is basically faster than Ack and it also has a lot of defaults. It's basically designed for programmers that want to search stuff recursively. So by default, there's already a lot of functionality. Now, what I'm going to show you is that there is a plugin that connects AG to Vim. [\[01:16\]](https://www.youtube.com/watch?v=fn0Et0b-rjY&t=76s) But first, you actually have to have AG installed on your system. So, you actually have to write you have to, for example, on a Mac, you'd have to brew install AG. And in this case, I I should already have it installed. So, that's not a problem. And by default, if you call ag inside a folder, you just say AG and then the word you're looking for. and it recursively searches and gives you nicely colored output to show exactly where things are. [\[01:47\]](https://www.youtube.com/watch?v=fn0Et0b-rjY&t=107s) And then there's this ag.vim plugin for Vim. And it's very very easy to install. I'll just literally just copy this. And at this point, I'm assuming that you've seen my video on how to install and use plugins. And I'm also going to very quickly open Vim here and use a shortcut for editing my vimrc file. [\[02:19\]](https://www.youtube.com/watch?v=fn0Et0b-rjY&t=139s) I I've mapped it to leader which in my case is comma leader EV. So I'm editing my vimrc file here. And if you're not sure what I just did, don't worry about it. There's a special video under the going fast section that shows exactly what I just did and how I map this stuff. It's this set of commands right here. But what I'm going to do is I'm going to install a new plugin here. I'm going to call it plug. And here I'm going to just command V and paste [\[02:53\]](https://www.youtube.com/watch?v=fn0Et0b-rjY&t=173s) The location for for this plugin. And now I'm going to write quit write and then quit and then source the file. And I have a command for that doing this whole thing right here. So I'm just going to type leader WQ and that's going to source my vimrc file and allow me to use the plugin. So, comma wq [\[03:26\]](https://www.youtube.com/watch?v=fn0Et0b-rjY&t=206s) And I'll just move this here so you can see my shortcuts from now on. And now I have actually have vim open. I'll have to do a command plugin install which will actually install the ag plugin. Now I already have it installed from for because I prepared a demo but that's what you would have gone through and from this moment on I can quit this file and if I wanted to just so you can see if I open NERDTree [\[03:56\]](https://www.youtube.com/watch?v=fn0Et0b-rjY&t=236s) This is where I am in my file system and if I just type command ag and then the word class what you'll see is that I now have two windows open one is the first result found is actually open in a window on top and then the bottom window is the window that's currently active. This is called a quick fix window and there's a bunch of shortcuts that I can use and it shows all the all the locations of where that word actually exists in files here and you can see here at the bottom I can press E to enter E T to tab a horizontal or vertical split. [\[04:38\]](https://www.youtube.com/watch?v=fn0Et0b-rjY&t=278s) Basically, if I wanted to, for example, open index as a split here, all I have to do is to say V or H. So, I'll just do V and it opened this file right there. And if I wanted now to move back into the bottom window, just like I'm using multiple windows, Ctrl W and and J will go down. Ctrl W and K goes up. Ctrl W and L goes right. So let me go down for a second here. [\[05:10\]](https://www.youtube.com/watch?v=fn0Et0b-rjY&t=310s) And so I can open this. I can open other.rb in another split window just like another V. And now I have these three windows open. So let me close the quick list window. I can literally just move to it and then type Q or there is a command called colon. This is the quickfix window starts with the C and I'll just say CL for close. CCL will close the quick fix window. [\[05:40\]](https://www.youtube.com/watch?v=fn0Et0b-rjY&t=340s) Now I have my three files and it's easy to move around. And if you want to understand all the options that AG has, just look up for the silver searcher command line reference. You should be good to go. Very simple, very nice, very easy. This totally takes away all the horrible stuff that is the grep syntax that I really really do not like and makes things much much easier to live with. [Previous lesson Ctrl-P](https://courses.osherove.com/courses/vim-hates-you/ctrl-p/) [Next lesson Mapping keys to actions](https://courses.osherove.com/courses/vim-hates-you/mapping-keys-to-actions/) --- title: "Mapping keys to actions" url: "https://courses.osherove.com/courses/vim-hates-you/mapping-keys-to-actions.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/mapping-keys-to-actions/" tags: [] author: "Roy Osherove" description: "Lesson 20 of 26 in Vim Hates You (Go Faster), 8:22. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Mapping keys to actions 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Go Faster Lesson 20 of 26 Duration: 8:22 [Watch on YouTube](https://www.youtube.com/watch?v=aChWve2LdXY) ## In this lesson Roy maps the down arrow to dd and p and the up arrow to dd, k and Shift-P with the map command, so that the arrows move the current line. He explains that map and its mode versions imap, nmap and vmap are recursive, so later mappings, including those of plugins, can change what they do, and recommends the non-recursive noremap commands. He then adds to his vimrc a noremap that opens NERDTree with Ctrl-N (ending with CR for Enter) and normal-mode noremap versions of the arrow mappings, and loads them with source. ## Transcript 1,108 words [\[00:07\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=7s) Talk about how we can bind keyboard shortcuts to anything we want to do in Vim. In this case, let's assume that I want to have the following functionality. I want to be able to move lines up and down just with a single keystroke. For example, if I wanted to move line five one line down, I would have to basically delete the line which is DD. And now that's right now in the clipboard of Vim. And then paste. And then that will paste it right after this line. So if I wanted to map that to the down arrow key, which I'm not supposed to be using in in Vim anyway, how would I do that? [\[00:42\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=42s) So one way to do that is with a command that later I'll show you why you shouldn't be using it. You should be using a different one. But the simplest command we can learn is called map. So I'm going to type colon map and I'm going to map the down arrow. That's how you write special keys into the following sequence of keys. DD and then P because that's what I would type. And that's it. If I just press enter now, [\[01:13\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=73s) If I'm moving up and down with J and K, nothing happens. But what watch what happens if I press the down arrow key. Now up doesn't do that yet. So let's map the up arrow as well. I'll do how would you move a line up? Well, you would have to do dd then go one line up and press shiftp like this. So let's try to map that. Map up [\[01:43\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=103s) To dd. go one line up which is K and then shift P. And that should be enough. Let's try and do that. So now if I'm moving I'm pressing the up arrow like this, you can see that it's actually moving the line down in the file. So that's pretty neat. So mapping in this in its simplest form is very very simple. [\[02:14\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=134s) However, we should not be using the map keyword. And the reason is is that the map keyword is fully recursive. In fact, if I wanted to, I could use this mapping and say these keys only apply in insert mode, in normal mode or in [visual mode](https://www.youtube.com/watch?v=aaCGJCJPSjA "Vimming - Natural Selection (YouTube)") by just saying IMAP, NMAP or VMAP. And if I just say map, it applies to all modes. But again the problem is even if it's visual normal or insert [\[02:46\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=166s) It will still be recursive. That means that in if I go back to vim when I mapped up to ddkp if I then tomorrow do another map to the letter d and I'm going to say whenever you type d I want you to do another following set of actions. the map keyword will actually recursively look up all these characters and expand them into whatever they mean. So it will then use those D's as basically two map command calls as well and expand them. [\[03:24\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=204s) So I will have weird behavior because I won't remember that I mapped that specific thing. Even worse, imagine that plugins are mapping specific things and they will override or you will unintentionally use their mappings. So, we should not use the map keyword. Instead, we should always be using the noremap basically. So, for example, noremap by default applies to everything. [\[03:56\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=236s) If I want to map but again non-recursive so no o no no no no re is not recursive insert non-recursive map normal non-recursive map or visual non-recursive map is basically how I I would go along with it so whenever you see all these things remember they're just mappings but they'll only work in specific modes like only if you're in insert mode can you will that shortcut actually work but the n is the mostant important part because that's the thing that says look even if you see characters that have been defined in other maps just use them as literal characters don't actually expand them into whatever someone else wrote. [\[04:39\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=279s) So that's the basic idea and of course we can use those commands and put them in our vimrc file so that they'll always be available just like I did here. I can say for example let's map NERDTreeToggle into controln because I don't want to type NERDTreeToggle every time. So how would I do that? Well, I technically I could just say noremap [\[05:13\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=313s) Because that's what I should always be doing if I want to map something to everything but not recursive. And let's say I want to say ctrlN for NERDTree. So for ctrlN you would say open c for control a for alt etc. S for shift. CtrlN will map to NERDTreeToggle. And this is very important. You have to type carriage return which is basically pressing enter because this is what vim will write for you in the command line when you type ctrlN. [\[05:52\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=352s) So now if I press enter here and now I try to press CtrlN you'll see that it calls this command dot vimrc oops I need to save this first going to edit I'm going to just pressing up edit home vrc and I add this specific command so I'm going to say [\[06:26\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=386s) Noremap. Controll N to NERDTreeToggle and CR because that's carriage return. And I can of course map my up and down arrows. So I can say in normal mode because I only want to do it in normal or maybe even in visual. Let's say normal mode. So normal noremap [\[07:00\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=420s) Up. Sorry, let's start with down because it's easier. I want to map that to delete the the line and then paste right where you are right after basically. And let's do the same thing. I'm going to copy this. I'm going to say change word. Let's move that to up and change that to shift C to change from this line on DD and then move up one line and then press shift P because you want to paste right above this will these two will only happen in normal mode. [\[07:44\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=464s) So now all I have to do is write and I can also type source for my vimrc like this commando for source and home slash vimrc. And now if I basically try to use my up and down arrows you'll see that it's already working. And if I use CtrlN, it's already working. So that's how simple and easy it is to map keys to specific actions in Vim. [\[08:16\]](https://www.youtube.com/watch?v=aChWve2LdXY&t=496s) Next, we're going to look at leader keys, which are a very powerful addition to this. ## Related ### Also linked in this lesson #### YouTube - [Vimming - Natural Selection](https://www.youtube.com/watch?v=aaCGJCJPSjA) [Previous lesson Find text in multiple files with AG](https://courses.osherove.com/courses/vim-hates-you/find-text-in-multiple-files-with-ag/) [Next lesson Mapping Leaders in Vim](https://courses.osherove.com/courses/vim-hates-you/mapping-leaders-in-vim/) --- title: "Mapping Leaders in Vim" url: "https://courses.osherove.com/courses/vim-hates-you/mapping-leaders-in-vim.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/mapping-leaders-in-vim/" tags: [] author: "Roy Osherove" description: "Lesson 21 of 26 in Vim Hates You (Go Faster), 3:57. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Mapping Leaders in Vim 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Go Faster Lesson 21 of 26 Duration: 3:57 [Watch on YouTube](https://www.youtube.com/watch?v=4x2N5JNaIcI) ## In this lesson Roy explains that the leader is a placeholder key, backslash by default, that many plugins use so that their mappings don't clash with existing key bindings, and that it can be changed with let mapleader. He maps the leader pressed twice to NERDTreeToggle and shows that, before the leader is set in the vimrc, the mapping works with two backslashes. He then sets the leader to comma in the vimrc, so two commas open NERDTree. ## Transcript 421 words [\[00:08\]](https://www.youtube.com/watch?v=4x2N5JNaIcI&t=8s) Let's talk about leaders. Leaders in Vim are basically placeholders for any key that you'd like. And the default for a leader is the backslash. Now, you can change it. And many plugins use leader mappings so that they don't clash with existing key bindings that they currently have. If you want to change the leader, you just say let map leader be comma, which is what I usually use. So in Vim, what I would do, I can say let map leader equal [\[00:38\]](https://www.youtube.com/watch?v=4x2N5JNaIcI&t=38s) Comma. And now what do I do? Well, I can set for example visibility of NERDTree just like I did previously. With let's say two map leaders. So I can say no let's say normal no re that's not recursive map [\[01:09\]](https://www.youtube.com/watch?v=4x2N5JNaIcI&t=69s) Leader leader to NERDTreeToggle and of course cr for enter at the Now let's see if that works. Now let me type two commas. Let's do that again. [\[01:42\]](https://www.youtube.com/watch?v=4x2N5JNaIcI&t=102s) Okay. So you can see that by using a map leader I can actually do a very very u powerful and generic thing and I can later change it. So if I don't feel comfortable with comma anymore I can change my leader to any other key that I'm comfortable with. So, I'll go to my vimrc and I'm going to say let's edit that. Let's edit the vimrc file and say here [\[02:14\]](https://www.youtube.com/watch?v=4x2N5JNaIcI&t=134s) Under normal not recursive map leader will be mapped to NERDTreeToggle with cr. So now I'll have two ways to open NERDTree and two leaders. Now, I haven't mapped the leader yet in in the vimrc. So, I just want to show you the default leader in this case. So, I'm going to write [\[02:47\]](https://www.youtube.com/watch?v=4x2N5JNaIcI&t=167s) I'm going to say source the vimrc. So, now if I press two leaders, I think because I mapped it in memory, this will still work. Let me close it down and do vim again. Now if I type two commas, nothing happens. But if I type two backslashes, I get NERDTreeToggle working. So let me go back and edit the vimrc. [\[03:22\]](https://www.youtube.com/watch?v=4x2N5JNaIcI&t=202s) And this time I'm going to say shift g to go all the way to the end. And right before all these mappings, I'm going to say shift O and say let map leader equal comma because that's the way I like to work. Escape O just to have an empty line between there and right quit. If I now open vimrc again, two commas and I have exactly what I need. [\[03:53\]](https://www.youtube.com/watch?v=4x2N5JNaIcI&t=233s) So that's how you use map leaders. [Previous lesson Mapping keys to actions](https://courses.osherove.com/courses/vim-hates-you/mapping-keys-to-actions/) [Next lesson Edit and source your .Vimrc faster](https://courses.osherove.com/courses/vim-hates-you/edit-and-source-your-vimrc-faster/) --- title: "Edit and source your .Vimrc faster" url: "https://courses.osherove.com/courses/vim-hates-you/edit-and-source-your-vimrc-faster.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/edit-and-source-your-vimrc-faster/" tags: [] author: "Roy Osherove" description: "Lesson 22 of 26 in Vim Hates You (Go Faster), 4:54. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Edit and source your .Vimrc faster 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Go Faster Lesson 22 of 26 Duration: 4:54 [Watch on YouTube](https://www.youtube.com/watch?v=E7WjGRnR0pk) ## In this lesson Roy creates two leader mappings to make changing the vimrc faster: leader ev opens the vimrc in a vertical split through a special variable that always points to the vimrc file, and leader wq writes and quits it and then sources it. He tests them by adding a mapping that opens NERDTree when the leader is pressed twice. He also shows that a mapping removed from the vimrc stays in memory until Vim is restarted. ## Transcript 644 words [\[00:07\]](https://www.youtube.com/watch?v=E7WjGRnR0pk&t=7s) It's become faster changing and sourcing our vimrc file so that we have less pain to keep changing it continuously as we work through things. I'm going to type commande and then my vimrc which is a special variable that always points to the correct vimrc file. And here if you remember we have a map leader which is our comma and I'm going to do a new mapping to open the vimrc file in a split and then I'm going to create another mapping to [\[00:39\]](https://www.youtube.com/watch?v=E7WjGRnR0pk&t=39s) Save the vimrc file and source it. So one mapping mapping one will open the vimrc file in a new split. mapping two will write and quit it and then source it. So these are the two mappings I want to create. So let's do that. [\[01:10\]](https://www.youtube.com/watch?v=E7WjGRnR0pk&t=70s) And norm map. So normal mode, no not recursive map. When you press leader and for me I'm going to type EV for edit vimrc file. I want that to map to a vsplit, sorry, vsplit and my vimrc variable and of course pressing enter at the end. And the second one, I'm going to copy this line and paste it right here and say leader. [\[01:46\]](https://www.youtube.com/watch?v=E7WjGRnR0pk&t=106s) Let's change it to right quit is basically not going to be a regular right quit. I'm going to type like comma wq and that will do the following. It will write quit, which is what I want, but then it's going to press enter, of course. And then it's going to say command [\[02:17\]](https://www.youtube.com/watch?v=E7WjGRnR0pk&t=137s) Source. Sorry, I have to do like a right quit here now that I forgot this. So, we're going to type right quit and press enter. Then, we're source my vimrc and press enter. So that's it. Now hopefully what's going to happen that if I'm going to I'm going to close this just once and I'm going to open Vim again. Now let's see what happens when I press leader EV. Leader EV and we have the split. [\[02:48\]](https://www.youtube.com/watch?v=E7WjGRnR0pk&t=168s) So let's change it. Let's add something here. Let's add a new mapping that will that we'll know definitely works. So, let's map a new leader to NERDTree. I want NERDTree to appear when I press leader twice. So, I'm going to copy this line and I'm going to add another one another shortcut leader leader and delete word delete word delete word and repeat with dot [\[03:22\]](https://www.youtube.com/watch?v=E7WjGRnR0pk&t=202s) And I want that to map to NERDTreeToggle as well because today if I press leader leader nothing happens. I have to press controlN but with this line active I should be able to see NERDTree just by pressing leader leader twice leader twice so let's save this again with our new shortcut which is this one leader write quit so leader WQ and I don't know if you've noticed but right at the bottom here we had a source of MRC that happened so let's see if that actually works I'm going to type leader leader and there we have our NERDTreeToggle. [\[04:01\]](https://www.youtube.com/watch?v=E7WjGRnR0pk&t=241s) Let's do that again. Let's try to open our vimrc leader EV. And now we can let's say delete this. Delete this line and leader right quit. And we had let's see if that works any that still works. Now the reason that still works is because the old bindings have not been removed just because they were removed from vimrc. They're still in memory. But if I close Vim again, sorry, I'm going to just quit because there's nothing to write and I open Vim again, the mapping doesn't work. [\[04:37\]](https://www.youtube.com/watch?v=E7WjGRnR0pk&t=277s) And technically, I could just say unmap, but I don't want to do that in my vimrc file if I don't have to. So that's one way you can get really more productive and much faster by editing your Vimrc file with special commands. Command leader EV leader right quit for example. [Previous lesson Mapping Leaders in Vim](https://courses.osherove.com/courses/vim-hates-you/mapping-leaders-in-vim/) [Next lesson Understanding Vim Registers](https://courses.osherove.com/courses/vim-hates-you/understanding-vim-registers/) --- title: "Understanding Vim Registers" url: "https://courses.osherove.com/courses/vim-hates-you/understanding-vim-registers.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/understanding-vim-registers/" tags: [] author: "Roy Osherove" description: "Lesson 23 of 26 in Vim Hates You (Go Faster), 8:37. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Understanding Vim Registers 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Go Faster Lesson 23 of 26 Duration: 8:37 [Watch on YouTube](https://www.youtube.com/watch?v=ZYz_K4RRjb8) ## In this lesson Roy lists registers with the reg command and pastes from one by typing a double quote, the register name and p, starting with the percent register, which holds the current file name. He shows the double quote register with the last copy or delete, the numbered registers for earlier deletes, the colon register for the last command, named registers such as a that keep a yank, and appending to a register with an uppercase letter. He also covers the black hole, small delete, last search and equals registers, and clearing all registers by removing the viminfo file. ## Transcript 1,293 words [\[00:08\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=8s) Let's talk about registers in Vim. To understand what registers are, the first thing we're going to do, we're going to type the command reg in the command window by typing colon reg and enter. And we see this list of just one item called registers. And this one item points to the current file name. And it starts with double quotes and then percent sign. Double quotes is how we access registers that contain meaningful information inside Vim. And the percent sign in this case is one special register that always contains the name of the current file. [\[00:40\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=40s) So let's say I want to paste the name of the current file inside my current file. I'm going to press enter to leave this. And if I wanted to paste it, all I have to do is to use again the double quotes to access a register, percentage to tell Vim which register to access and then P to paste it or shift P if I want to paste it the line above etc. So let me try this double quotes percent P and I get the name of the file. [\[01:12\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=72s) Okay, now I'm going to actually type DD to delete the current line. And now I'm going to type the reg command again. And this time we see the list has changed. First of all, we see that the first item is a double quote double quote, which is again a special register. The special double quote register always contains the last thing that was either copied or deleted [\[01:42\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=102s) So that we can paste it again later on. And then we have a double quote one which also contains the text of the thing I just deleted. And this is what's called a numbered register. And then and as I copy more and more things you're going to see double quote one, double quote two, etc. which basically allows me to go back nine places in memory to the things that I deleted before. So I can kind of see and retrieve up to nine things I deleted without even doing an undo. [\[02:16\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=136s) The third thing the third register you see is double quote colon which basically is another special register that tells me always contains the last command that I executed basically is a string and again the last one is the name of the file. So, we have some of these special registers and I'll talk about some better overview registers later on as well. But let's see what else we can do. [\[02:48\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=168s) I can create my own registers. For example, I can go down in the file and let's say select these two lines and I can save them into a specific register by again saying double quotes the name of the register which could be for example the letter A and then pressing Y for yanking for copying. So let's try that and see what happens. Double quotes a yank. [\[03:18\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=198s) And what happened now is that I have register reg which is the letter A that contains the text that I just copied. So now no matter what, no matter if I've deleted or copied other things whenever I want, I can always paste from this special register. So for example, I can go down in the file by pressing Ctrl + D writing a new line here. Escape. I just want to paste that again. [\[03:48\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=228s) Or you know what? Let me copy some more things. Shift V, go up, yank. Just yank them into default. If I try type reg now, you'll see that my double quote double quote actually contains the last copy, but it's different from the double quote a. That's always saved. So, I can always go back and paste just the A1 by saying double quote a paste, please. and I get that thing. So you can have basically all the letters and a bunch of characters, a bunch of symbolics as well as registers [\[04:26\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=266s) Which allows you great flexibility. Another thing you can do is instead of replacing you can append to a specific register. So for example, if I have V selected just these four characters and I say double quote B yank. Now what's going to happen if I press reg is you can see that under the B right here I have the word dark. [\[04:57\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=297s) Let's say I wanted to append to that. I can say instead of just using the letter B, I'm going to use an uppercase B which appends to it. So I'm going to say double quotes B yank. And since I only have D selected right now, if I press reg, oh, I didn't have anything selected. So let's select something else. Let's select this word ve. So to select until the end of the word and I'm going to say double quotes uppercase yank [\[05:32\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=332s) Which if we look at reg now for the register B we now have dark and mids appended to each other. So we can append to existing registers easily. One way to get rid of existing registers is a way that I've not shown yet, which is basically recording a macro that doesn't do anything into that specific thing. And another way if you wanted to clean out all your registers, what you do is you [\[06:08\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=368s) Remove the viminfo file which you have in your home folder which contains among other things the location of of all the registers and their contents. So just to recap here are some of the register we talked about and a couple we haven't. First we have named registers and you just use the double quotes to type double quotes the name of register in an action. For example, you want to copy the whole line. [\[06:38\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=398s) You just say double quotes a and then y will copy the whole line into the a register. And you have the default register which always takes the last delete or the yank or the copy. Basically we have the numbered registers which is basically the most recent deleted text. We have black hole register. Basically, if you want to discard of something, you don't want it to get saved to a register, you save it to the black hole register, which is kind of like dev null in Linux. And the idea is that nothing that goes in never comes back basically. [\[07:10\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=430s) Then we have a small delete register. So, if you've deleted something that's shorter than a line by pressing X, for example, or just selecting a few characters inside a line and deleting them, they're going to get saved in that special double quote minus. The last inserted text register will always be at the double quote dot, but if you just want to paste the lasted the last text you pasted before, just use the actual dot command instead of the register. So, you don't need to use this one. [\[07:42\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=462s) The current file name will always be a double quotes percentage. The most recent command will always be a double quotes colon. The most recent search that you've done will be double quotes slash forward slash. And there's a special kind of a weird register that saves the results of other registers. So if you want to say double quotes equals and basically put in the result of something for example double quotes equals 1 + 1 you will actually have the number two inside the register if you wanted to paste it and this might be good for you if you're doing any kind of programming or like special plugins you that might be useful to you otherwise just use a simple calculator even in command line. [\[08:28\]](https://www.youtube.com/watch?v=ZYz_K4RRjb8&t=508s) So that's it for registers. [Previous lesson Edit and source your .Vimrc faster](https://courses.osherove.com/courses/vim-hates-you/edit-and-source-your-vimrc-faster/) [Next lesson Vim and the System Clipboard](https://courses.osherove.com/courses/vim-hates-you/vim-and-the-system-clipboard/) --- title: "Vim and the System Clipboard" url: "https://courses.osherove.com/courses/vim-hates-you/vim-and-the-system-clipboard.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/vim-and-the-system-clipboard/" tags: [] author: "Roy Osherove" description: "Lesson 24 of 26 in Vim Hates You (Go Faster), 4:57. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Vim and the System Clipboard 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Go Faster Lesson 24 of 26 Duration: 4:57 [Watch on YouTube](https://www.youtube.com/watch?v=wyf3-dB_r94) ## In this lesson Roy checks whether a Vim build supports the system clipboard by looking for the word clipboard in Vim's version output, where grep helps, and a minus sign means it is not supported, as with the built-in Vim on most Macs. He installs MacVim with brew, overriding the system Vim, after which clipboard shows a plus. He then pastes text copied from Hacker News through the plus register (double quote, plus, p) and yanks a line into the system clipboard with double quote, plus, y. ## Transcript 675 words [\[00:07\]](https://www.youtube.com/watch?v=wyf3-dB_r94&t=7s) One of the most annoying things about Vim to me is how to use the system clipboard. Now, technically, in each system, you have to have a specific Vim that's integrated with the current system to be able to work with the system clipboard. in in on a Mac you can check if your Vim supports the system clipboard by default by basically saying Vim and then version and then looking for the word clipboard in the version. So if you see the minus sign next to a clip next to clipboard or external clipboard, it means that the current Vim that you have on your system does not support it. [\[00:46\]](https://www.youtube.com/watch?v=wyf3-dB_r94&t=46s) And by default on most Macs the the built-in Vim does not support clipboard which means you cannot copy paste using special shortcuts into the console or into Vim. However, you can still use commandV and and command C to copy and paste from the system clipboard. It's just not the let's say the Vim way. And you're going to get a little bit of a weird behavior sometimes because whenever you paste into Vim using shiftV, [\[01:17\]](https://www.youtube.com/watch?v=wyf3-dB_r94&t=77s) It's going to take longer and Vim is going to try to basically interpret every character as you're pasting it. The the the one thing that we can do is we can install a different Vim version. And the way that you can install this is basically on Mac, I highly recommend using either downloading a zip file from vim.org or for Mac or looking for a MacVim download or just use the brew [\[01:47\]](https://www.youtube.com/watch?v=wyf3-dB_r94&t=107s) To install basically brew install MacVim and you can say over override system Vim which basically will install Vim and override it so that when you try to open vim you're going to get this. If I'm opening a new tab here and I say which vim sorry [\[02:19\]](https://www.youtube.com/watch?v=wyf3-dB_r94&t=139s) Which vim I should be getting this this path right here. If I didn't install it yet here, and I say which Vim, this is the default Vim. So, if I do a, Vim version here, I can see that the clipboard is minus. And by the way, if I don't grep, this is what the full thing looks like. [\[02:51\]](https://www.youtube.com/watch?v=wyf3-dB_r94&t=171s) That's why grep is important just to see what you care about. And if I do a Vim version here, you can see that the clipboard, the regular clipboard is a plus, an external clipboard is minus because it's not a system that uses the X11 view. So it doesn't need that kind of integration. So that's what you should be looking out for. But once you have that and you turn on Vim and let's say that we are that we have a bunch of stuff in the system clipboard. [\[03:24\]](https://www.youtube.com/watch?v=wyf3-dB_r94&t=204s) So let me just copy a piece of text from let's say Hacker News. Okay. So I'm going to say just copy this how cars get named command C and go back. And if I want to paste this there there are there's basically a special register for the system clipboard and that register is the plus. So you access it just like any other register. You say [\[03:55\]](https://www.youtube.com/watch?v=wyf3-dB_r94&t=235s) The name of the register but before that you say double quotes and then you say paste or yank into that. So, double quotes plus paste and I get what I had in the system clipboard. And this is usually a much faster, way to to work in terms of the way Vim interprets the paste. And if I wanted to, I can select the whole thing or I can write a whole [\[04:26\]](https://www.youtube.com/watch?v=wyf3-dB_r94&t=266s) Line here. Escape, shift V to select the whole line. and I want to put it in the system clipboard. I'm going to say double quotes plus yank. And now if I go into let's say and I try to paste the blind text, I get this. So that's how you work with the system clipboard and you make sure that your Vim is fully aligned to actually allow this kind of workflow. [Previous lesson Understanding Vim Registers](https://courses.osherove.com/courses/vim-hates-you/understanding-vim-registers/) [Next lesson Abbreviations in Vim](https://courses.osherove.com/courses/vim-hates-you/abbreviations-in-vim/) --- title: "Abbreviations in Vim" url: "https://courses.osherove.com/courses/vim-hates-you/abbreviations-in-vim.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/abbreviations-in-vim/" tags: [] author: "Roy Osherove" description: "Lesson 25 of 26 in Vim Hates You (Go Faster), 2:25. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # Abbreviations in Vim 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Go Faster Lesson 25 of 26 Duration: 2:25 [Watch on YouTube](https://www.youtube.com/watch?v=PEPc_OOS1_8) ## In this lesson Roy describes abbreviations as text completions on the fly: he defines one that expands my email into his email address, which could also be kept in the vimrc, and in insert mode it expands as soon as he types a character that is not alphanumeric. He suggests them for long text such as copyright notices and email signatures, or for common spelling mistakes. Unlike a mapping, an abbreviation is only expanded when it is typed outside of another word. ## Transcript 347 words [\[00:09\]](https://www.youtube.com/watch?v=PEPc_OOS1_8&t=9s) In Vim are really yummy little snack feature kind of thing. Kind of like a little popcorn that you can put into your Vim soup and just enjoy it continuously and add to it as much as you like. And basically they're just text completions on the fly. You know, let's say that you always type your email and you don't want to write your email always. You just want to have text auto expanded to that. Well, you just type the command. Sorry, let's out get out of insert mode. Type the command IB [\[00:40\]](https://www.youtube.com/watch?v=PEPc_OOS1_8&t=40s) Riv. I just type tab to go there. and you just say when I type my my email, I want you to expand it to roy.com. So now if I have that or if I had that in my vimrc, all I have to do is to say let's go into insert mode. My email is my email. And if I press anything that's not alpha numeric, [\[01:11\]](https://www.youtube.com/watch?v=PEPc_OOS1_8&t=71s) It gets expanded automatically. And technically, we could always configure Vim to say on what it gets expanded on, etc. But that's the basic idea. You can just have abbreviations for things that are long like copyright or email signatures or or sometimes people use them just for common spelling mistakes uppercase lowerase mistakes. Anything really is just a really simple powerful nugget that you use. Now you might ask why wouldn't I use that instead as a u binding as a mapping and the answer is that mapping does not take does not take into account the text that you wrote before. [\[01:54\]](https://www.youtube.com/watch?v=PEPc_OOS1_8&t=114s) So technically I could type that text my email into a mapping but then if it was inside another word then that other word would get halfway would get expanded into my text. This does not happen if I just use abbreviations because Vim is smart enough to know what came before the abbreviation, what came after, and it looks specifically for the fact that you type the abbreviation outside of a word. So that's it. Hope you enjoy this little nugget. [Previous lesson Vim and the System Clipboard](https://courses.osherove.com/courses/vim-hates-you/vim-and-the-system-clipboard/) [Next lesson VIm Macros](https://courses.osherove.com/courses/vim-hates-you/vim-macros/) --- title: "VIm Macros" url: "https://courses.osherove.com/courses/vim-hates-you/vim-macros.md" canonical: "https://courses.osherove.com/courses/vim-hates-you/vim-macros/" tags: [] author: "Roy Osherove" description: "Lesson 26 of 26 in Vim Hates You (Go Faster), 5:37. Free video by Roy Osherove." usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)." license: "https://creativecommons.org/licenses/by/4.0/" --- # VIm Macros 1. [Courses](https://courses.osherove.com/#courses) 2. [Vim Hates You](https://courses.osherove.com/courses/vim-hates-you/) 3. Go Faster Lesson 26 of 26 Duration: 5:37 [Watch on YouTube](https://www.youtube.com/watch?v=8R2HatvL0wE) ## In this lesson Roy explains that q and a letter start recording a macro into that register, q again stops it, and the @ sign with the letter plays it back, optionally with a count. To build a numbered list he records a macro into n that yanks and pastes a line and increments its number with Ctrl-A, looks at it with the reg command and runs it 10 times with 10@n. He then pastes the macro into the vimrc as a leader mapping, and notes that a count does not work with that mapping. ## Transcript 734 words [\[00:08\]](https://www.youtube.com/watch?v=8R2HatvL0wE&t=8s) Vim macros are one of those things that a lot of people hear about, but a lot of them don't really actually use, but they're actually pretty simple. The way Vim macros work is that you press the letter Q, and then you decide on a letter or a number that will be used as that as that macro location. Usually, it's a letter. And then you press and then you do something with your keyboard and it's being recorded. And then once you finish, you just basically just type Q again. And then the macro stops recording. [\[00:38\]](https://www.youtube.com/watch?v=8R2HatvL0wE&t=38s) And from that moment on, whatever you just did is in that register. And you then you want to execute it, you press the add sign and then the letter you just recorded to and then the macro is executed. And of course, you can put a number before that. And then the macro gets executed multiple times. So for example, let's say you wanted you you don't always use them, but when when you do use them, they save a lot of time. Let's say you have a task of creating, I don't know, a thousand lines or editing a,000 lines with the same type of actions. [\[01:11\]](https://www.youtube.com/watch?v=8R2HatvL0wE&t=71s) You can use macros for that. Here's a simple example that a lot of people use to display this power. If I wanted to create a list of 10 items, just the numbers, I can start by saying one, right? And then escape. But now I want to create a macro that copies the line and then increments the number using a [\[01:42\]](https://www.youtube.com/watch?v=8R2HatvL0wE&t=102s) And and basically does that multiple times. So, let me hit Q and let's choose a the end character because I'm creating numbers and because I waited too long it the macro didn't start. So, let me start again and press QN. Now, you see at the bottom it says recording to the N macro [\[02:13\]](https://www.youtube.com/watch?v=8R2HatvL0wE&t=133s) To the N register. So now I'm going to do Y to copy the row P. And now I'm in the second row. And I'll press Ctrl+ A to increment the number. And that's it. So I'm going to press Q again to stop recording. If I want to see this macro, I can type command reg to see my registers. And you'll see that in the double quotes n [\[02:44\]](https://www.youtube.com/watch?v=8R2HatvL0wE&t=164s) I have this exact set of steps. So technically I could even paste it into my vimrc file and use that as a command later. So let me repeat that 10 times. I'm going to say 10 at n and this repeats. Let's do it a th00and or 500 just for the sake of argument. 507 at n and here we are. So macros are very powerful. [\[03:14\]](https://www.youtube.com/watch?v=8R2HatvL0wE&t=194s) Let's see if we can add this to our vimrc and say write quit and e sorry vim home vrc. So, I'm going to go down to the bottom and I'm going to paste the contents of that macro. So, if you remember the the macro is in a register and I have a whole video about mapping and registers, but to access it, I'll say double quote n and then just paste. [\[03:54\]](https://www.youtube.com/watch?v=8R2HatvL0wE&t=234s) And here I have it here. So, let me map this. I'm going to say N O remap. So in normal mode, no not recursive map, my leader key and I covered that in a separate video and N for number or maybe my leader key and then NN for for this macro and that will equal this set of actions. [\[04:26\]](https://www.youtube.com/watch?v=8R2HatvL0wE&t=266s) And I can basically execute that multiple times. So let's see. I'm going to right quit open my index html and let me just delete from this from this line. Shift G, delete. And I'm going to write a new line here that says one. [\[05:00\]](https://www.youtube.com/watch?v=8R2HatvL0wE&t=300s) And let me see if I can do a leader. In my case, leader is comma. So leader n and I have this. Let's try and do 10 leader andn. That didn't work because those numbers do not work with those different types of commands. We would have to do that separately. And we can do that as Vim functions, which I'm not covering yet in this course. But that's an example of how you can save or not lose. If you're doing really, really complicated actions, you want to save them as a one-off. [Previous lesson Abbreviations in Vim](https://courses.osherove.com/courses/vim-hates-you/abbreviations-in-vim/) [Last lesson Back to the course overview](https://courses.osherove.com/courses/vim-hates-you/)