Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs •...

68
Automated Testing with Umbraco … or any other website you build

Transcript of Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs •...

Page 1: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Automated Testing with Umbraco

… or any other website you build

Page 2: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Who am I?

• Lars-Erik Aabech

• Professional web developer since 1998

• Working at MarkedsPartner AS since 2002

• Umbracian since 2012

• Certified V5 developer (!!!)

– Also V7 master

• Umbraco Core MVP x 3

• Avid fan of SOLID principles and Automated Testing

Page 3: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

WHY AREN’T WE UNIT TESTING?

Page 4: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

We don’t have the time!

Page 5: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Code Build(Re)Start

WebserverStart browser

Wait for runtime compiles

Click aroundVerify

Page 6: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Code Build(Re)Start

WebserverStart browser

Wait for runtime compiles

Click aroundVerifyDebug

Page 7: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

AUTOMATEDTESTS!

Page 8: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Code Build

Run TestsAutomagically

verify

Page 9: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Code Build Run Tests

Automagically verify

Debug

Page 10: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

We don’t have the time to learn how to unit-

test!

Page 11: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

EFFO

RT

FEATURES / TIME

Tests No tests

Page 12: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

We don’t have the time to learn how to do our

job properly!

Page 13: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

We don’t want to learn how to do our job

properly!

Page 14: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

HOW?

Page 15: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Example: Recently Used List

• A nice little Kata to train on

• Last in, First out

• If it were already there, it’s moved to the top

Page 16: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

1990’s: «Drivers»

• Throw-away console apps for proof of concept

• Throw-away web-pages with buttons that invoke functions

• Throw-away windows with buttons that invoke functions

• Big-ass logfiles or console outputs logging shitloads of stuff to textboxes or output

Page 17: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs
Page 18: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs
Page 19: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

1999: Self Testing Code

“Self-Testing Code is the name I used in Refactoring to refer to the practice of writing comprehensive automated tests in conjunction with the functional software. When done well this allows you to invoke a single command that executes the tests - and you are confident that these tests will illuminate any bugs hiding in your code”

- Martin Fowler, https://martinfowler.com/bliki/SelfTestingCode.html

Page 20: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs
Page 21: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

2K: Automated Unit Tests

• Kent Beck publishes Test Driven Development: By Example (2002)

• A mindset for development and driving design

• The tests verify their own results

– AKA Assert.ThisAndThat()

• A set of classes and functions designed to run in unordered sequences

• All the «drivers» automated without apps or buttons to click

• Comprehensive list of results for each feature

• No need for logging and manual verification

Page 22: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs
Page 23: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

BENEFITS?

Page 24: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

SPEED!(Fast feedback)

Page 25: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

SELF ESTEEM!(I know my code worked 2 minutes ago)

Page 26: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

DOCUMENTATION!(Examples)

Page 27: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

REFACTORING!(Refactoring without tests is just moving shit around

– Corey Haines)

Page 28: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

What’s a unit?

A function

A class

A set of classes

A webpage

An application

A unit is whatever your team decides is a unit

- Martin Fowler

Page 29: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

The simplest units

• A function using, manipulating and returning simple values

• A class manipulating its own inner state, exposing or returning some value(s)

POCOPlain Old C# Object

Page 30: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

HERE BE DRAGONS!

Page 31: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Mr. AssertTooMuch

• Asserting several things in a tests is a mistake

• It’s actually a breach of the Single Responsibility Principle

• If the first assert fails, you won’t know about any successive failures

• It’s a lot of code to write

My name is Mr. AssertTooMuch

Well you’d better cut down a bit, then.

Page 32: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Meet ApprovalTests

Page 33: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs
Page 34: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Meet ApprovalTests

Method Purpose

Verify Text / Whatever

VerifyAll Lists of whatever

VerifyBinaryFile Unreadable, but approvable ☺

VerifyHtml Formats HTML nicely

VerifyJson Formats and compares JSON nicely

VerifyPdfFile Like binary, just more PDF’y

VerifyXml Formats XML nicely

Extendable! Whatever you want, however you want

Page 35: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Meet ApprovalTests

#H5YR@LlewellynFalco

Page 36: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Then there were two...

Page 37: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Then there were two...

• Two or more classes interacting, perhaps across modules

• The one doesn’t work without the other

• «System Under Test» and «Collaborators»

• Testing two or more artifacts together is per definition an integration test

Page 38: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

The problems

IO Databases

Webservers Umbraco ☺

NON-POCO:’(

Page 39: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

DEPENDENCY INVERSION!

Page 40: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs
Page 41: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Test Doubles

• AKA. Fakes, Mocks, Stubs

• Replaces the collaborating class with a dumb object satisfying the tested class’ needs

• Removes dependencies on IO, Databases, Webservers and others

• Either handwritten (fakes) or using a library that creates such types at runtime. (dynamic stubs/mocks)

Page 42: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

HERE BE DRAGONS!

Page 43: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Mr. StubTooMuch

• One stub can be a lot of code to set up

• Two stubs are even more

• Every property and method call have to be declared

• Can become completely unmaintainable

• You have no idea whether the «real» collaborator will do the same thing

My name is Mr. StubTooMuch

Well you’d better cut down a bit, then.

Page 44: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs
Page 45: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

The dragons are many!

• Using test doubles may require a lot of extra code

– Writing a fake may be the quickest way

• Stubbing without effective means of setting up data creates heaps of unreadable and unmaintainable code

– Stubbing is useful when the output can be deserialized instead of fleshed out in the test

• Mocks are not stubs!

– Mocking is only meant to verify external calls or calls to IO

• You might end up hating unit-testing.

Page 46: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

INTEGRATE!

Page 47: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs
Page 48: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Go to the database if you want

• Make sure to create a fresh one for each test run

• Seed it with data that all tests expect

• Start a transaction and roll it back after each test

• Incidentally this is dead easy to do with Entity Framework + «Code First»

Page 49: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

RazorGenerator

• Design-time generates «codebehind» for views

• Lets you render views without a webserver

• Combined with ApprovalTests is a definite win for verifying GUI

Page 50: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

On acceptance tests

• NUnit isn’t the only framework

• Scenarios can be expressed in Wallet-Speak with a language called «Gherkin»

• Scenarios written in Gherkin are ran with «Cucumber»

• Regular expressions match yourtext to your code

• In .net «Cucumber» is called «SpecFlow»

• Properly layered they can be ran against your domain code, or through the GUI with Selenium on a whim.

Page 51: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs
Page 52: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

The test pyramid and the types of automated tests

Acceptance(a few)

Integration (quite a few)

Unit Tests(a lot)

Page 53: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

The ice cream cone of automated tests

Acceptance(a lot)

Integration (quite a few)

Unit Tests(a few)

Page 54: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

What about legacy software without tests

• Start adding tests when making new features

• Introduce abstractions by «extract interface» to introduce «seams»

• Change private, protected and internal to public (!!!)

• Read «Working effectively within legacy code» by Michael Feathers

Page 55: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

ENOUGH, LARS!GET TO

UMBRACO ALREADY!

Page 56: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

EXPLOIT THE CORE TESTS!

Page 57: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Core Tests and Internals

• The core tests already stub everything you need to run Umbraco in a test context

• Available as a community build on Nuget (Thanks Christian Thillemann/@kedde!)

• 20+ base classes to inherit depending on how much you need support for

• All the annoying internal things can be exposed by introducing an «adapter assembly» called «Umbraco.UnitTesting.Adapter»

• Can still require a bit too much code

Page 58: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

UmbracoSupport

• General class to include instead of inheriting Umbraco’s base tests.

– Actually inherits BaseRoutingTest

• All the stubs and core integrations you’ll need for Umbraco 7

• Extensive samples for most use-cases athttps://github.com/lars-erik/umbraco-unit-testing-samples

• (You still have to set things up)

Page 59: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Composition vs. Inheritance

• Inheriting Umbraco’s tests block your own inheritance

• Support classes can be brought in as you need them

• Typical support classes

– UmbracoSupport

– DatabaseSupport

– ExternalServiceSupport

• The support classes contains the stubbing so you don’t need to repeat it

• Simple API-calls on the support classes to set up stuff using POCOs

Page 60: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

UMBRACO 8?

Page 61: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

DEPENDENCY INVERSION

EVERYWHERE!\o/

Page 62: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

EVERYTHING CAN BE

STUBBED! \o/

Page 63: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

CurrentUmbracoContext.

Page 64: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

NUCACHE AND THE CURSE OF

INTERNALS

Page 65: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

UmbracoSupport for V8 TODOs

• All the base classes are still there

• We can still use XML, but there’s nowhere to copy from

• DI is all around now

• Yet Current is used all over

• Everything can be stubbed!

• We need test APIs to help reduce friction

Page 66: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Come join the discussion

• We have several paths to our goal

• There are fakes ready, but internal in the test project

• There are real classes ready to integrate, and they might just as well be public…?

• Proposal: Publicize everything, but tag candidates for breaking changes such that the Roslyn compiler throws an error when they’re used. Add an attribute in your test assembly to override this as an «EULA» for using volatile classes.

• Should published content be at the forefront of our testing?

• https://github.com/umbraco/Umbraco-CMS/pull/5325

Page 67: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

Let’s find the sweet spot betweenintegration and stubbing to make us

as fast as possible when we buildcomplex sites.

Page 68: Automated Testing with Umbraco - Umbraco Codegarden 2019 · • AKA. Fakes, Mocks, Stubs • Replaces the collaborating class with a dumb object satisfying the tested class’ needs

QUESTIONS?