Coder Social home page Coder Social logo

tdd-example's Introduction

Test-Driven Development

Hello! This repository shows a practical example of how to use TDD to develop an application given some requirements.

The principles behind the tests and application design here are driven by what Ian Cooper advises in his TDD: Where Did It All Go Wrong? video. Seriously: watch it.

NO, SERIOUSLY: WATCH IT.

What Ian says in that video is how these tests have been constructed, and its joyous to work in this way :)

Requirements Implemented

  1. We need a way to store musicians and their best songs.
    • A musician only needs their name and best song to be stored.
    • There should only be one entry for each musician.
  2. We need a way to retrieve a musician and their best song based on their name.
  3. We want to allow upvotes on an entry.

Directory/file structure

Note that the files are organised into src and tests at the top level to denote source code and test code, respectively.

src

Directories within the src directory are organised by domain concepts, rather than class functions. These directories are intended to create a set of layers, or stack for the domain concept. The sub-directories are intended to define the following structure:

                           THE WEB
                              ^
          | --------- |       |       | --------- |
          |  DOMAIN   |       |       |  DOMAIN   |
          | CONCEPT X |      / \      | CONCEPT Y |
          | --------- |     /   \     | --------- |
PORTS     | REST Port |<----     ---->| Rest Port |
          | ----^---- |               | ----^---- |
          |     |     |               |     |     |
          | ----v---- |               | ----v---- |
PUBLIC    |  Service  |<---Concept--->|  Service  |
          | ----^---- |               | ----^---- |
          |     |     |               |     |     |
          | ----v---- |               | ----v---- |
PRIVATE   | Repository|               | Repository|
          | --------- |               | --------- |

What this diagram is trying to convey is a combination of domain-driven design (domain concepts), hexagonal architecture (Ports), and a layered/stratified architecture (Ports, Public, Private). The layers in each stack can evolve in isolation and may contain more than just one module in each layer.

I call these stacks "domain stacks" and they are there to promote encapsulation. If you follow this architecture, you'll essentially end up with a modular-monolith. Here I'm suggesting an architecture where:

  1. Other systems outside the app call-in via the Ports layer. Ports from different domain stacks don't talk to one another, but do talk to the next immediate layer down in the stack; the Public modules. Port modules are usually integration modules.
  2. Public modules are so-called because these modules can talk across domain stack boundaries so are "public" from the perspective of the application's domain stacks. Modules within this structure are usually high-level interfaces that expose operations that can be performed in context of a domain concept. They are usually integration modules. Public modules can also talk to layers below them, and they can respond to the modules in the "ports" layer above. You could think of these as a specialisation of the service layer pattern
  3. Private modules are so-called because these modules don't talk across domain stack boundaries. They are only able to call other Private modules, or respond to the Public modules within their own domain stack. They are usually operation or hybrid modules.

tests

https://youtu.be/e7dx2Z9G7Mk?t=18

OK but, in all seriousness, this is where the business is. Some technical details first:

  • Tests are written and run using the Jest framework. There's no special reason for this, its just what I'm comfortable with at the moment in Javascript!

  • testcontainers are used in all tests. This is because TDD should be testing the public interface of a module and, for a web application, this is the REST API. Yes, I know, some of you may want to fight on this but please, watch this.

external-dependencies

Contains external dependencies that can be set-up as containers for use during testing by testcontainers.

tdd-example's People

Stargazers

Philip Wong avatar James Carroll avatar

Watchers

James Carroll avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.