45
Unit Testing in .NET

Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

  • Upload
    others

  • View
    89

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Unit Testing in .NET

Page 2: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Philosophy of Unit Testing

• What?

• Where?

• Why?

• How?

• What it is not?

Page 3: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

• Test individual components (units)

• in isolation

• to confirm preexisting specification.

• Inputs … -> expected results

• Test functions, methods.

• Use a framework to make it easier (xUnit or ?Unit)

isolate and validate

verify

Page 4: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

• Write tests after creating specification, but before implementing methods.

• Best if written by the developer or the development team. Why?

• Test-driven development

• Supports regression testing

Page 5: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

The Art of Unit Testing, by R Osherov

Page 6: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test
Page 7: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test
Page 8: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test
Page 9: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

1 Unit Test

assertions

Page 10: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Test Suite

Test Case

Test Case

Test Case

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Unit testUnit testUnit test

Run with TestRunner

Page 11: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Assertions

http://junit.sourceforge.net/javadoc/org/junit/Assert.html

JUnit

assertEquals() assertFalse() assertNotNull() assertNotSame() assertNull() assertSame() …

By the way, you should use assertions in everyday programming

Java: assert i > 0; C#: Debug.Assert( i > 0 ); Python: assert i > 0

Page 12: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

NUnit Assertions

Classic ModelAssert.isEmpty() Assert.areEqual() Assert.Null() Assert.notNull() …

https://github.com/nunit/docs/wiki/Classic-Model

Constraint Model

Assert.That()

https://github.com/nunit/docs/wiki/Constraint-Model

Page 13: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

NUnit

Assert.That( aString, Is.Empty ); Assert.That( aString, Is.Not.Empty ); Assert.That( 2 + 2, Is.EqualTo(4.0) ); Assert.That( 5.5, Is.EqualTo( 5 ).Within(1.5).Percent ); Assert.That( "Hello!", Is.Not.EqualTo( "HELLO!" ) ); Assert.That( "Hello!", Is.EqualTo( "HELLO!" ).IgnoreCase );

constraint

Page 14: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Good Habits• Try to make tests independent or orthogonal to other tests

• Test only one code unit at a time

• Don’t name your tests: test0, test1, …

• Use setup and teardown to create a clean environment for each test

• Don’t have unit tests access your database — use fake data (write a “mock” object that meets the same interface) ==> break dependencies

• Refactor to make your code more testable

• Discover a flaw at the component level? Write unit tests first to expose it (reproduce it). Then fix the error.

• Run tests prior to committing (or merging) your code

Page 15: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Start Simple• Test methods with no dependencies

• Make sure constructor doesn’t have dependencies

input Method output

Page 16: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

NUnit Demo (2017)• Add a new project to your solution: Visual C# -> Test

• Remove MSTest parts: reference, using and packages.config

Microsoft.VisualStudio.QualityTools.UnitTestFramework //using Microsoft.VisualStudio.TestTools.UnitTesting <package id=“MSTest.TestAdapter” version=“1.1.11” targetFramework=“net452” /> …

• Add NUnit to your test project using NuGet, packages:

NUnit v3.2.0

NUnit3TestAdapter v.3.0.9-ctp-9 (needs “Include prerelease” checked)

• Add MVC framework using NuGet (since separate project isn’t an MVC app)

Microsoft.AspNet.Mvc (Match the version # of your main project, mine was v.5.2.3)

• Add reference to your own project

Had to delete %AppData$/NuGet/NuGet.Config to load “online” package sources

Page 17: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

• Add Visual Studio Test Generator

• Optionally install Visual Studio Test Adapter as an extension rather than locally within the project

• Restart Visual Studio and finish installation

Page 18: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Find something to test

Page 19: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Write your unit test class:

Page 20: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Run Tests: Test -> Windows -> Test Explorer

Page 21: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Harder

input

Function

output

Database

Internet

Page 22: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Not Unit Testable

Page 23: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Not Unit Testable

Page 24: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Why Not?

• “Uncontrolled” dependencies

• All or most functionality in 1 method, with no separation and no “control” over it

• Code is doing more than 1 thing

Page 25: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Arrange — Act — Assert• Arrange

Set up for the test. Configure the system one way or another. Must be able to do this.

• Act

Execute or invoke something, with some input, to obtain some output. Must be able to do this.

• Assert

Usually the easy part.

Page 26: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

SOLID• Single responsibility principle

a class (module, method or function) should do one thing and one thing only

• Open/closed principle

• Liskov substitution principle it should be possible to substitute in fakes, stubs or mocks without fundamentally changing anything

• Interface segregation principle create segregation of responsibilities and become agnostic of implementors by replacing concrete classes with interfaces (having the minimum of functionality required)

• Dependency inversion principle (and Inversion of Control) invert the “high-level module depends on low-level module” pattern. Break direct dependencies by using dependency injection pattern and providers.

https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)

Page 27: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

The Art of Unit Testing, by R Osherov

Page 28: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test
Page 29: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test
Page 30: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test
Page 31: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test
Page 32: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test
Page 33: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Problem?

Just a stub for now

Page 34: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

One Solution: inject via

constructor

will be other logic here, i.e. test the name not just the extension

Page 35: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test
Page 36: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test
Page 37: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

• Up Next …

• Testing code that reads/writes to a database

• Use a “mocking framework” to make it easier, i.e.

• Moq: https://github.com/Moq/moq4

• Use [SetUp] and [TearDown] to seed your mock object

Page 38: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Controller

DbContext

EntityFramework

Database

Default Setup

Page 39: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Controller

DbContext

EntityFramework

Database

Using Repository Pattern

ActualRepoForTestingRepo

ISomethingRepository

An interface

Page 40: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Need to modify to allow constructor

injection

Page 41: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Inject mock object

Page 42: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Sports Store Example from

Entity - Single table

Page 43: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Break dependency with Repository pattern

Page 44: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

pagination

constructor injection

Page 45: Unit Testing inmorses/classes/cs46x/lecture/UnitTesting.pdfThe Art of Unit Testing, by R Osherov. 1 Unit Test assertions. Test Suite Test Case Test Case Test Case Unit test Unit test

Unit Test Pagination