class: center, middle # Unit Testing 101 ## "Write your first unit tests in C#" ### Cesar Aguirre _Software engineer, lifelong learner_ --- ## Agenda ### What and Why * What is a Unit Test * Why you should write Unit Tests? * What code should I test? * What is a good test? ### How * How to Organize my tests * How to Name my tests * Arrange/Act/Assert * Assertion Frameworks * MsTests * Example: Stringie Remove method --- class: center, middle ## What and Why --- ## What is a Unit Test? > "A unit test is an automated piece of code that invokes a unit of work in the system and then checks a single assumption about the behavior of that unit of work." .footnote[Source: [Unit Test - Definition](https://www.artofunittesting.com/definition-of-a-unit-test/)] --- ## But, what is a Unit of Work? A Unit of Work is any logic exposed through public methods that * returns value, * changes the state of the system * or makes an external invocation We shouldn't be testing private methods directly --- ## Why you should write Unit Tests? * Allow change * Prevent bugs from happening again * Have living documentation --- ## Analogy  .footnote[Photo by [Loic Leray](https://unsplash.com/@loicleray?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/circus?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)] --- ## What code should I test? Test any code that contains logic in the form of * Conditionals * Loops * Calculations --- ## What is a good test? Write F.I.R.S.T * Fast * Independent * Repeatable * Self-validating * Timely --- ## When should I write my unit tests? Before or after the production code? 1. Test first: Test-Driven Development 2. Test later Make sure you always see your tests failing --- class: center, middle ## How --- ## How to Organize my tests ### Project ```bash MyLibrary MyLibrary.UnitTests ``` ### Class ```bash MyClass.cs MyClassTests.cs MyClassTests.AnAwesomeFeature.cs ``` --- ## How to Name my tests ### A sentence ```csharp ItShouldThrowAnExceptionWhenDividingByZero ``` ### UnitOfWork_Scenario_ExpectedResult ```csharp Divide_Zero_ThrowsException ``` --- ## Arrange/Act/Assert ```csharp public void Divide_Zero_ThrowsException() { // Arrange // Act // Assert } ``` --- ## Assertion Frameworks * [NUnit](https://github.com/nunit/nunit) * [MSTest](https://github.com/Microsoft/testfx-docs) * [XUnit](https://github.com/xunit/xunit) --- ## MSTest ### Create a test method ```csharp using Microsoft.VisualStudio.TestTools.UnitTesting; namespace MyLibrary.Tests { [TestClass] public class MyClassTests { [TestMethod] public void MyTestMethod() { } [TestMethod] public async Task MyAsyncTestMethod() { } } } ``` --- ## MSTest ### Assertion methods ```csharp Assert.AreEqual(expected, actual) Assert.AreNotEqual(notExpected, actual) Assert.IsFalse(condition) Assert.IsTrue(condition) Assert.IsNotNull(value) Assert.IsNull(value) Assert.ThrowsException
(() => SomeAction()); Assert.ThrowsExceptionAsync
(async () => await SomeActionAsync()); ``` --- ## Example: Stringie Let's write some tests for Stringie, a library to transform strings with a fluent interface. ```csharp string transformed = "Hello, world!".Remove(); // "" string transformed = "Hello, world!".Remove("Hello"); // ", world!" ``` --- ## Example: Stringie Remove method ```csharp using Microsoft.VisualStudio.TestTools.UnitTesting; using Stringie; namespace Stringie.Tests { [TestClass] public class RemoveTests { [TestMethod] public void Remove_SingleWordToRemove_ReturnsEmpty() { var str = "123456"; var removed = str.Remove("123456"); Assert.AreEqual(0, remove.Length); } } } ``` --- ## It's your turn Write at least 3 unit tests for Stringie. Clone this repo and follow the instructions on the README file .center[[](https://github.com/canro91/Testing101)] --- class: center, middle > _"Legacy code is code without tests"_ > > Working Effectively with Legacy Code, Michael Feathers --- ## To learn more about this subject Check one of my posts * [The C# Definitive Guide](https://canro91.github.io/2018/11/17/TheC-DefinitiveGuide/) * [How to write good unit tests? Avoid these two issues](https://canro91.github.io/2020/11/02/UnitTestingTips/) * [How to write good unit tests? Have a failing test](https://canro91.github.io/2021/02/05/FailingTest/) * [How to create fakes with Moq](https://canro91.github.io/2020/08/11/HowToCreateFakesWithMoq/) * [The Art of Unit Testing: Four Takeaways](https://canro91.github.io/2020/03/06/TheArtOfUnitTestingReview/) --- class: center, middle # That's all folks! ## Cesar Aguirre https://canro91.github.io/