Image

Learn how to test real, complex software written in Go

Large or small, perfect abstractions or global state galore; it doesn't matter what your code looks like, you CAN learn to test it.

Tell me if this sounds familiar - you are learning how to test in Go, and things seem to be going great. The tutorials are all clicking, and you can't wait to start applying what you are learning in your real projects.

You fire up your editor, grab your latest project, create your first *_test.go source file, and suddenly it feels like you don't have a clue what you are doing.

*You hear the sound of glass shattering*

What happened?!?!

Things were going so great. All those examples made sense, but now you don't even know where to start.

It seemed so easy to test that "Hello, world" HTTP handler, but how do you test complex handlers? You know, HTTP handlers that do something realistic like insert a record into a database, or use an API to verify someone's address.

For that matter, how do we verify that our database interactions are working as we expected? Or maybe your app has a global DB variable - does that mean testing simply isn't possible?

What about those APIs we are interacting with? Do we stub them? Do we hit the test API? What happens if we hit API rate limits or there isn't even a test API?

Alright, alright! Take a second to breathe and let me fill you in on a little secret...

Testing isn't hard, but simple tutorials don't do it justice

Testing isn't any harder than writing any other Go code. In fact, if we wanted we could test our code by just writing a main package and interacting with our application code. We could panic when something doesn't act the way we expected, and viola - we have a test!

But why does it feel so hard? Probably because we simplify the examples to the point that they lose all of their value.

Think about it, when is the last time you wrote a Palindrome function?

Never? So why are all these tutorials showing us how to test one?

Why aren't they showing us how to test realistic software? What happened to the example where we test a real HTTP handler that needs access to a data store? Or the tutorial where we build an API client and learn how to test it WITHOUT always hitting the real API. Wouldn't it be great if we could learn how to test a real web app with a real DB and a real integration to a payments API like Stripe?

Test with Go is different.

In this course you will learn how to test REAL software, not palindrome functions.

We will have to look at a few isolated examples in order to learn specific testing techniques, but that isn't enough to solidify a concept so we won't stop there. We will build real projects that teach you how to apply all of these testing skills in real software.

In one project we build a web application which allows us to address the complexities that come up while testing an application that uses a database, third party APIs, and more. In another project we look at how internal testing helps us verify our intermediate steps are correct, while also discussing the downside to testing unexported functions.

You will learn about common pitfalls to avoid in order to write more testable code. You will learn how to incrementally fix code that has already succumbed to many of these pitfalls, allowing you to avoid a massive PR that makes your reviewer cry inside.

When you run into an application with a global DB variable you won't need to give up on testing. You will learn exactly how to make small, manageable changes to the code that allow you to start testing it almost immediately.

The next time you are asked whether the data store should be mocked or if a real SQL database should be used you will be able to discuss the pros and cons of both approaches with your teammates and decide on a proper plan of action.

After completing this course you will have the knowledge and the skills necessary to start testing your own projects. You will still have to put in the work, but the mystery, the confusion, and the frustration will be gone.

In short, you will be on your way to becoming the de facto testing expert on your team. You will be on the path to making your team's software a happier, healthier place to spend your day. Heck, you might even be on your way to a raise or a better offer! 😉

Want a sample of the course?

or learn about the course below

Course Overview

Test with Go is broken into two major sections: Lessons and Projects

Put together, the lessons and projects span 173 videos and total over 33 hours of content.

In the lessons we focus on learning the techniques necessary to test our applications. We will learn the basics, like how to write your first test and what table driven testing is, but we will also cover more advanced testing techniques like:

We will spend some time using small, isolated examples in order to learn each technique, but those will gradually become more realistic as you become familiar with testing. Before long we will be looking at tests that use a real SQL database, test helpers that enable us to test HTTP endpoints that require authentication, and more.

In the projects we will take everything we learned in the lessons and practice applying them while building real software. We will look at some of the most common mistakes you can make when designing an application, as well as how to gradually refactor your code to make it more testable. We will see first-hand how to separate your integration and unit tests, allowing you to write tests for an API client that can both be run locally and online with the real API. We will even look at how to export some of those helper functions, making it easier for others who use your libraries to write tests.

More can be seen in the individual Lessons and Projects sections below.

I finished my internship this week. The knowledge I got from your book helped me get a better offer (compared to the average around here), and I'm glad. Thank you.
Jonathan B.
Software Engineer
Image

The Lessons

The lessons consist of 88 videos that will gradually walk you from the most basic exercise - like writing your first test - all the way to advanced techniques like interface test suites, dependency injection, and more.

All of the lessons are broken into sections, making it easier to quickly jump to the subject you want to learn or review. That means in a few years when you want a quick reminder on testing subprocesses you can quickly find the section you need and get back to testing your code with minimal downtime.

Section 1: What is testing, and why does it matter?

Image

What is a test?

Image

Why do tests matter?

Image

Writing great tests

Section 2: Tests are just Go code

Image

Testing with a main package

Image

Testing with Gos testing package

Image

What happens when we run go test

Section 3: Naming conventions

Image

File naming conventions

Image

Function naming conventions

Image

Variable naming conventions

Section 4: Failing tests

Image

Ways to signal test failure

Image

When to use Error vs Fatal

Image

Writing useful failure messages

Section 5: Examples as test cases

Image

A basic example as a test case

Image

Viewing examples in the docs

Image

Unordered example output

Image

Complex examples

Image

Examples in the standard library

Section 6: Testing multiple cases

Image

Table driven tests

Image

Generating table driven test code

Image

Subtests

Image

Shared setup and teardown

Image

TestMain

Section 7: Parallel tests

Image

Running tests in parallel

Image

Parallel subtests

Image

Setup and teardown with parallel subtests

Image

Gotchas with closures and parallel tests

Section 8: Testing race conditions

Image

What is a race condition

Image

The race detection flag

Image

Testing explicitly for race conditions

Section 9: Comparing objects for equality

Image

Simple comparisons

Image

Reflect's DeepEqual function

Image

Golden files (brief overview)

Image

Helper comparison functions

Section 10: Testing utilities

Image

Building things with helper functions

Image

Generating test data

Image

Gos quick testing package

Image

Public testing utilities

Section 11: Controlling which tests are run

Image

Running specific tests

Image

Running tests for subpackages

Image

Skipping tests

Image

Custom flags

Image

Build tags

Section 12: Additional testing flags

Image

Benchmarks

Image

Verbose testing

Image

Code coverage

Image

The timeout flag

Image

Parallel testing flags

Section 13: External and internal testing

Image

Differences between external and internal

Image

How to write internal and external tests

Image

When to use external tests

Image

Exporting unexported vars, funcs, and types

Image

When to use internal tests

Section 14: Types of tests

Image

Overview of test types

Image

Unit tests

Image

Integration tests

Image

End-to-end tests

Image

Which test type should I use

Section 15: State

Image

What is global state

Image

Testing with global state (if you must)

Section 16: Dependency injection (DI)

Image

What is dependency injection

Image

DI enables implementation agnostic code

Image

DI makes testing easier

Image

DI and useful zero values

Image

Removing global state with DI

Image

Package level functions

Image

Summary of DI

Section 17: Mocks, stubs, and fakes

Image

What is mocking

Image

Types of mock objects

Image

Why do we mock

Image

Third party packages

Image

Faking APIs

Section 18: Interface test suites

Image

What are interface test suites

Image

Interface test suite setup and teardown

Image

Interface test suites in the wild

Section 19: Testing with HTTP

Image

httptest.ResponseRecorder

Image

httptest.Server

Image

Build HTTP helpers

Section 20: Golden Files

Image

What are golden files

Image

Updating golden files

Section 21: Testing subprocesses

Image

What is a subprocess

Image

Running the subprocess in tests

Image

Mocking simple subprocesses

Image

Mocking complex subprocesses

Section 22: Testing with time

Image

Why are dates and times problematic?

Image

Inject your time and sleep functions

Image

Testing timeouts

Section 23: Bonus material

Image

Colorizing your terminal output

Image

Coverage info function

Image
I realize you are looking for ways to improve, but I don’t have anything negative to say about the videos you sent me to review. I love your approach in these lessons. Everything is explained well and I can’t wait for the course release!
Nestoras Stefanou
Software Engineer

The Projects

There are three projects in this course:

Each project is built from the ground up with the goal of teaching you about testing in real software. For instance, we will intentionally make mistakes that make our code hard to test then explore ways to make it more testable. Or in other instances we might discuss the tradeoffs of one approach vs another before ultimately moving forward and writing any code.

The videos for each project are shown below, and if you have any questions don't hesitate to reach out and ask.

*The projects are only included in the COMPLETE package

Project 1: form

A Go package (AKA a library) used to generate HTML forms from Go structs

Image

01. Topics covered in the form project

Image

02. The first test

Image

03. Our first bug

Image

04. Handling multiple fields

Image

05. Field values

Image

06. Checking for specific attributes in a test

Image

07. Unexported fields

Image

08. Non-structs are invalid

Image

09. Pointers to structs

Image

10. Supporting more types

Image

11. Generating HTML

Image

12. Discussing struct tags and tests

Image

13. Parsing struct tags

Image

14. Applying struct tags

Image

15. Golden test files

Image

16. Struct tag tests in TestHTML

Image

17. Rendering errors

Image

18. Rendering errors

Image

19. Detecting breaking changes with tests

Project 2: stripe

An API client used to interact with a few of the Stripe payment API endpoints

Image

01. The first test

Image

02. Creating a customer

Image

03. Versioning our client

Image

04. Making the API key a flag

Image

05. Improving our customer data

Image

06. The charge endpoint

Image

07. Custom error type

Image

08. Parsing stripe errors

Image

09. Customer endpoint errors

Image

10. Starting on unit tests

Image

11. Allowing customer http clients

Image

12. Creating a recorder client

Image

13. Persisting recorded responses

Image

14. Making our tests cross-platform

Image

15. Serving recorded responses

Image

16. Unique customer per charge subtest

Image

17. Adding tests for specific errors

Image

18. Helper functions

Project 3: swag

In this project we explore how we might approach adding tests and refactoring a web application that wasn't designed with testing in mind. We look at how to incrementally add tests and make changes so we avoid breaking any functionality or needing to make massive overhauls to the code.

The web app we add tests to allows users to order sticker packs using both the form and stripe packages we create in the first two projects

Image

01. What to expect

Image

02. App overview

Image

03. Initial db tests

Image

04. Creating the db.Open function

Image

05. What about mocks

Image

06. Test harnesses and helpers

Image

07. Reviewing tests

Image

08. Testing specific times

Image

09. First pass at refactoring the db pkg

Image

10. Updating db tests

Image

11. Testing the order flow

Image

12. Extracting code for unit testing

Image

13. Extracting the active campaign handler

Image

14. Unit testing the active campaign handler

Image

15. Table driven testing the active campaign handler

Image

16. Refactoring campaign middleware

Image

17. Unit testing the campaign middleware

Image

18. Starting the orders handler

Image

19. Testing the new order handler

Image

20. Refactor Create order handler

Image

21. Test: Create order handler

Image

22. Integration testing with Stripe

Image

23. Testing for specific Stripe failures

Image

24. Another form of table driven tests

Image

25. Refactor: Order middleware

Image

26. Test: Order middleware

Image

27. Refactor: Show order handler

Image

28. Test: Show order handler

Image

29. Don't get too clever

Image

30. Integration testing the show order handler

Image

31. Removing sql from the confirm order handler

Image

32. Testing the database confirm order function

Image

33. Refactor: Confirm order handler

Image

34. Test: Confirm order handler with same address

Image

35. Test: Confirm order handler when campaign isnt found

Image

36. Refactoring and finishing the confirm order handler unit tests

Image

37. Integration test: Confirm order handler

Image

38. Setting the stripe secret key via ENV variable

Image

39. Refactoring the routing code in main

Image

40. Testing our asset directory

Image

41. Mocks for testing our router

Image

42. Testing the show order route

Image

43. Table driven router testing

Image

44. Additional router testing

Image

45. Removing the tempDB type

Image

46. Removing the DefaultDatabase package variable

Image

47. Cleanup

Image

48. Wrapping up

Image
I expected to learn some useful testing techniques and strategies, which I most definitely did, but thinking about what Jon teaches in this course has begun to change the way I think about writing code in general; an unexpected benefit.
Thomas
Software Engineer

Course Packages

Complete Package
Image
Access to everything. The lessons, the projects, the source code, and future updates.
173 videos totalling over 33 hours of content.
Stream or download the videos from any device. You could be learning to test with Go even when you don't have internet access!
Access to all the source code used in the course
Free course updates - anytime I update or add any new content you will get instant access to it. That include new lessons, projects, etc.
Learn how to test a Stripe payments API integration
Slack
Access to the exclusive Test with Go course Slack. Ask questions and learn with both me and others who purchased the course
Lessons Package
Image
Access to all the lessons and their corresponding source code.
88 videos totalling over 13 hours of content
Stream the videos from any device
Access to all the source code used in the lessons
Free lesson updates - anytime I update the lessons you will get instant access to the updated material
Slack
Access to the exclusive Test with Go course Slack. Ask questions and learn with both me and others who purchased the course

Buying more than one copy?

In addition to individual packages, I also offer team packages. These include everything in the complete package, but you get a discount for buying multiple copies. You can reach out to discuss a team package that fits your team's needs.

You have the best practical learning materials available. I've been studying Go for more then one year and saw lots of materials. But yours stuff is the best!
Alex D.
Software Engineer
Image
FAQ

Frequently Asked Questions

What if I don't like it?

I offer a 30 day money back guarantee. If you are unsure about the course, I recommend purchasing the package you feel is best and streaming a few of the videos to see if the course is right for you. If it isn't, send me an email within 30 days and I'll issue you a refund.

This only applies to the first time you purchase a course. I do not offer multiple refunds for the same course, so if you purchase a course, request a refund, then purchase it again I will not offer a second refund. This is because I am still charged the CC processing fee on a refund, and it isn't reasonable for me to eat that cost multiple times.

I may also refuse a refund in extreme cases. For instance, if you buy the course, download a large portion of the videos, then request a refund. I have had issues with theft in the past, so I reserve the right to refuse a refund in cases like this.

If you have any questions about this policy, please reach out before purchasing. I am genuinely trying to help people and will try to work with anyone, but a few bad actors have unfortunately made it hard to offer refunds without some restrictions.

How long will I have access to the course?

The course doesn't expire. Once you purchase, you will always have access to the videos.

If you are worried, the complete package includes a way to download all the content so that you can back everything up on your own devices as well. You know, just in case I get hit by a truck or something. 🚛 *beep* *beep*

What formats are the videos in?

The videos are hosted with Vimeo and are streamable through their embedded player. If you purchase the complete package I also offer DRM-free, high quality 1920x1080 mp4s that you can download.

Where is the section on TDD?

The short answer? There isn't one.

We use TDD some in the projects, but it isn't taught as a standalone concept. That said, everything taught in this course can be applied to TDD with relative ease.

Do you offer student discounts?

Yes, students of any kind (high school, college, bootcamp, whatever else) can send me an email with any sort of proof you are a student and I'll send you a link to purchase the course with the student discount.

Do you offer team packages?

Yes, I offer team packages. These include everything in the complete package, but you get a discount for buying multiple copies. Reach out for more info - [email protected].

About the Author

Jon Calhoun is a full stack web developer who teaches about Go, web development, testing, algorithms, and anything else he finds interesting. He spoke at the GothamGo conference about focusing on simplicity when writing software and is a panelist on the Go Time podcast.

Previously, Jon founded EasyPost, a shipping API that many fortune 500 companies use to power their shipping infrastructure. Before that he worked at Google as a software engineer. Before that he studied computer science at UCF.

You can find more of Jon's work, including other FREE courses and tutorials he has created, below.

Test with Go was created by @joncalhoun. The awesome gophers you see above were designed by @egonelbre and slightly tweaked by me (if you see a mistake, it was probably me).
© Jon Calhoun 2018. All rights reserved.