Property-Based Testing with test.check
Property-Based Testing is a powerful way to test your software. In this course, we learn how to use test.check, the Clojure Property-Based Testing library, to automatically generate tests.
This course is currently in the PurelyFunctional.tv Early Access Program. The price you see below is a significant discount off the normal price. It's more than 50% off. I can't say exactly how much it will cost when it is finished, but I can say this is as inexpensive as it will ever be. The course will probably be 5-7 hours of video when finished.
Property-Based Testing with test.check
Want this course?
Love it or leave it guarantee
If you don't learn as much from this course as you thought, just ask for a refund within 30 days and I'll give you your money back.
1. What is Property-Based Testing?
Property-Based Testing is a way to generates lots and lots of tests so you don't have the write them. It finds bugs and helps you design your software. In this introduction to the course, we learn what Property-Based Testing is.
2. What is test.check?
test.check is the Property-Based Testing library we'll be using in this course. In this lesson, we'll take a look at the origin of this library, how it integrates with Clojure, and how it's getting a lot of attention from the Clojure core team.
3. Advantages of Property-Based Testing
Property-Based Testing has several advantages over regular Example-Based Testing. It's worth calling them out.
4. When can you use Property-Based Testing
Property-Based Testing can be used at four different times, from design-time to after your users have found a bug, to help you reproduce it.
5. How does Property-Based Testing work?
In this lesson, we go through the basic algorithm used by test.check to test our code and show us useful failures. The algorithm gives us a map of the things we will have to learn.
6. An overview of property-based testing with an example test
In this lesson, we will see an example of the process of testing an existing function using Property-Based Testing.
7. A tour of the built-in generators
test.check comes with many built-in generators that we can use to create properties and build new generators from. We take a tour of the generators provided so we have a feeling of what's available.
8. Building your own simple generators
We can put together generators that we need from the existing generators. There are four tools provided by test.check that help us do this. In this lesson, we go over such-that, fmap, bind, and let.
9. Building complex generators: email address
We use Strings a lot in programming, but often our Strings are assumed to have very specific formats. We need to be able to generate Strings that are still random, yet fit the format. In this lesson, we see how we can build a new generator by generating the pieces of the String and putting them back together.
10. Building complex generators: matrices
Sometimes the data we need to generate is complex and can't easily be done directly. In that case, we can often do well by generating instructions to build the value. In this lesson, we see how that can be applied to generating random matrices of different sizes.
11. Strategies for properties: functionality
Coming up with properties is hard. So we need some strategies to try out when we need to come up with them. In this lesson, we go over two ways to directly test the functionality of a function.
12. Strategies for properties: invariants
Coming up with properties can be a challenge. One strategy is to look at what doesn't change. In this lesson, we take a look at testing invariants.
13. Strategies for properties: algebraic properties
I often run through a short list of algebraic properties, the ones you learn in Algebra class, to find properties to test. In this lesson, we go over six properties that you can use and modify to your needs.
14. Strategies for properties: generate the output
Sometimes it is not possible to generate the input directly. And sometimes it is not possible to test the output without reimplementing the function you are testing. In either of these cases, you could always do the opposite of what's normal: generate the OUTPUT and convert it to an input.
15. Strategies for properties: metamorphic properties
Sometimes you need to test something that doesn't have a right answer. Metamorphic properties let you test a system against itself. If you modify the input, you should see a modification of the output.
16. Behind the scenes: size
It's important to know about size. Size controls the range of values of a generator. It changes over the length of a run of a property. The built-in generators have an intuitive notion of size, and you can control the size yourself using three functions from the generators namespace.
17. Behind the scenes: shrinkage
When a test case fails, the shrinkage process begins. It takes the failing test case and tries to make it smaller so that it's easier for the programmer to isolate the problem. In this lesson, we look inside the shrinkage process. It's not something you have to think about all the time, but sometimes you do.
18. Building complex generators: mutation testing
Sometimes you want to test values that are almost right. Random values won't cut it. What you can do is to generate correct values and mess them up. That's called mutation testing, and it's what we look at in this lesson.
19. Testing pure functions
Pure functions are the easiest things to test. You can run them as many times as you want without fear of side effects. In this long episode, watch over my shoulder as I test five different functions. Three of the functions are fairly mathematical, so they're pretty straightforward. But two are copied from real-world code. You'll get to see the raw process, right here.
20. Testing stateful systems
Testing mutable systems that keep state is slightly harder than testing pure functions, but PBT is up to the challenge. In this lesson, we test two different systems and encounter the challenges we face with gusto!