Testing

Rainer Stropek | @rstropek

Introduction

Rainer Stropek

  • Passionate software developers for 25+ years
     
  • Microsoft MVP, Regional Director
     
  • Trainer, Teacher, Mentor
     
  • 💕 community

Tic Tac Toe

Let's build a (slightly over-engineered 😜) TicTacToe game and learn about unit testing strategies on the way.

Sample code is available on GitHub

Ubiquitous Language, Rules

  • We play on a board
  • A board consists of 3 x 3 squares
  • The content of each square can be empty, X or O
  • A game is played by two named players
    • Player 1 starts and turns an empty square into X
    • Player 2 follows and turns an empty square into O
    • This is repeated until one player has three in a row, in a column, or in a diagonal line. This player is the winner.
    • If there are no empty squares left and there is no winner, the game is a draw.

Learnings

  • No unit testing without good requirements
  • Tests should reflect requirements
    • Ubiquitous language
    • Acceptance criteria
  • Developers shouldn't have to fill in the blanks
    • Missing or unclear requirements lead to over-engineering
    • Over-engineered code is hard to test
    • Missing acceptance criteria, test data etc. is a productivity killer for deverlopers

Level 1: Project
Setup, Basic
Tests

Demo
Time!

Avoid Unnecessary Testing

  • Use the full power of the C# compiler
  • You don't need to write tests for errors that the compiler finds
  • Check code on build servers, not just on your local machine
  • Apply good coding practices to test code, too
    • Avoid over-engineering (e.g. invent testing frameworks)
    • Tests the tests: Write tests for complex testing code

Demo
Time!

House Rules

  • Use descriptive names for tests classes and methods
    • Remember: Use ubiquitous language
    • Avoid inventing new terms and abbreviations
  • Add documentation to clarify what each test verifies
    • Remember: Code is more often read than written
  • Unit tests must be fast!
    • Remember: There are other test categories, too (e.g. integration tests, end-to-end tests, perf benchmarks, manual tests, etc.)
    • Here: Focus on unit tests

Level 2: Writing
Tests With
xUnit

Demo
Time!

Tips

  • Do not make members public to make them available to unit tests
    • Prefer InternalsVisibleTo
  • Use proper xUnit assertions
  • Use theories instead of facts where appropriate
  • Write tests for happy cases and error cases
    • Validate exceptions, in particular for public members
  • Check test coverage
  • Consider VS Live Unit Testing

Level3:
Fixtures, Mocking,
Integration Tests

Demo
Time!

Shared Test Context

  • Initialize tests in constructor
    • xUnit runs constructor for each test
  • Cleanup (if necessary) in IDisposable
  • Use Fixtures for sharing context across tests

Demo
Time!

Mock Objects

  • Use interfaces or virtual methods for isolating workloads
    • Here: IBoardContent
    • Examples:
      • Test logic, not dependencies between classes/modules
      • Test logic without backing DB or cloud services
      • Discuss: What is a unit in unit testing?
  • ​Use a mocking framework (e.g. Moq)

Demo
Time!

Testing 🤘

Rainer Stropek | @rstropek

Unit Testing With xUnit and Moq

By Rainer Stropek

Unit Testing With xUnit and Moq

  • 583