Matthew Butt Unit Testing the Hard Stuff · .NET Web API [Whiteboard] Designed for Test Directly...

Post on 15-Mar-2020

0 views 0 download

Transcript of Matthew Butt Unit Testing the Hard Stuff · .NET Web API [Whiteboard] Designed for Test Directly...

Matthew Butt

Unit Testing the Hard Stuffmatthewbutt.com @bnathyuw

NB

There will be codeIt will be C#I will explain it

Axiom:

Unit Tests are Importantfeedback for delivering quality software

SpeedControl

Precision

Observation:

Some projects have no Unit Tests

Why?

Why?not Designed for Test

few Techniquesfew Tools

not even many Workarounds

Unit Testingthe Easy Stuff

Designed for TestTools

Techniquesor at least Workarounds

.NET Web API

[Whiteboard]

Designed for Test

Directly ExecutableObject OrientedAbstractionsDI

Techniques

SOLID designMockingArchitecture Patterns

(MVC, ports & adapters, hexagonal…)

Tools

NUnit… test framework

NSubstitute…mocking framework

OWIN… in-memory host

Workarounds

Adaptersaround leaky abstractions

Mock Clockand other system dependencies

Speed Run locallyControl Test doubles

Precision Class levelClear purpose

Outside-in approach

Acceptance test outer loop

Unit test inner loop

Acceptance Test

In-Memory HostStub Externals

Controller Test

In-Memory HostTreat as adapter

Mock DependenciesTest interactions

Keep it thinNo domain logic

Domain Object Tests

State or Interaction?State: stubs

Interaction: mocks

Single ResponsibilityListen to your tests!

External dependencies

AbstractionsInterfaces in Domain

Integration testsNo test if trivial

Clock

namespace EasyStuff.Api.Domain {public interface IClock {

DateTime Now { get; }}

}

namespace EasyStuff.Api.Adapters {public class SystemClock : IClock {

public DateTime Now => DateTime.UtcNow;}

}

var knownDate = new DateTime(2001, 2, 3);var clock = Substitute.For<IClock>();clock.Now.Returns(knownDate);

Unit Testingthe Hard Stuff

Microsoft AzureData Lake Analytics

Financial TransactionsWeather Data

AberporthLocation: 224100E 252100N, Lat 52.139 Lon -4.570, 133 metres amslEstimated data is marked with a * after the value.Missing data (more than 2 days missing in month) is marked by ---.Sunshine data taken from an automatic Kipp & Zonen sensor marked with a #, otherwise sunshine data taken from a Campbell Stokes recorder. yyyy mm tmax tmin af rain sun degC degC days mm hours 1970 1 7.5 3.1 7 97.5 40.2 1970 2 6.2 1.9 7 79.2 96.2 1970 3 6.6 2.0 8 76.1 101.2 1970 4 8.8 4.2 2 67.0 135.2 1970 5 14.5 8.5 0 28.1 148.9 1970 6 18.5 11.5 0 47.3 206.5 1970 7 16.6 11.3 0 57.4 150.3 1970 8 17.8 12.3 0 42.6 151.8 1970 9 16.8 11.5 0 49.4 120.4 1970 10 13.3 8.6 0 108.3 75.4 1970 11 10.8 6.4 0 181.4 41.7 1970 12 7.5 3.3 6 42.9 69.4 etc. etc. etc.

aberporthdata.txt

ExtractTransform

Load

[Whiteboard]

Not Designed for Test

Hosted in CloudNot Directly ExecutableHybrid CodeClosely Coupled

Few Tools

A library from MSabstractions too leaky

Local Test Runnerthis is useful

Few techniques

SQL unit testsfairly gruesome

Few workarounds

Google doesn’t help

Outside-in approach

Acceptance test outer loop

Unit test inner loop

Acceptance Test

Local Run Helper

U-SQL Script TestHybrid code

U-SQL & C#

Data on file system

Responsibility of Script

Orchestrator or

Query

Seam U-SQL // C#

Inline code Nope!

Code-behindNah…

AssembliesNow you’re talking!

Substitute AssembliesCode is compiled for each execution

Duck typing

Substitute at runtime

Stub or Mock?Not directly availableFakes against file system

User-Defined Objects

Leaky Abstraction

Use of StreamsTemporal CouplingStrange Idiom>1 Responsibility

Adapter layerTranslate between framework & domain

Domain Tests

Familiar Territory

You may still need to Mock the Clock!

What have we learnt?

Speed Run locallyControl Seams

Test doublesPrecision Small pieces

Clear purposeAdapters

PatternsPatterns

Patterns

ResourcesTesting Patterns github.com/bnathyuw/testing-patterns/wiki

Example implementation github.com/bnathyuw/weather-data-iii

Dank je wel!