So far, we have been doing example-based testing. We judiciously divide the input space of a program (into partitions), pick one concrete example from all the possible ones, and write the test case. What if we did not have to pick one concrete example out of many? What if we could express the property we are trying to exercise and let the test framework choose several concrete examples for us? Our tests would be less dependent on a concrete example, and the test framework would be able to call the method under test multiple times with different input parameters—usually with zero effort from us.
This is what property-based testing is about. We do not pick a concrete example; rather, we define a property (or a set of properties) that the program should adhere to, and the test framework tries to find a counterexample that causes the program to break with these properties.