I tend to use anything that offers property-testing, since tests are much shorter to write and uncover lots more hidden assumptions.<p>My go-to choices per language are:<p>- Python: Hypothesis <a href="https://hypothesis.readthedocs.io/en/latest" rel="nofollow">https://hypothesis.readthedocs.io/en/latest</a> (also compatible with PyTest)<p>- Scala: ScalaCheck <a href="https://scalacheck.org" rel="nofollow">https://scalacheck.org</a> (also compatible with ScalaTest)<p>- Javascript/Typescript: JSVerify <a href="https://jsverify.github.io" rel="nofollow">https://jsverify.github.io</a><p>- Haskell: LazySmallCheck2012 <a href="https://github.com/UoYCS-plasma/LazySmallCheck2012/blob/master/README.md">https://github.com/UoYCS-plasma/LazySmallCheck2012/blob/mast...</a><p>- When I wrote PHP (over a decade ago) there was no decent property-based test framework, so I cobbled one together <a href="https://github.com/Warbo/php-easycheck">https://github.com/Warbo/php-easycheck</a><p>All of the above use the same basic setup: tests can make universally-quantified statements (e.g. "for all (x: Int), foo(x) == foo(foo(x))"), then the framework checks that statement for a bunch of different inputs.<p>Most property-checking frameworks generate data randomly (with more or less sophistication). The Haskell ecosystem is more interesting:<p>- QuickCheck was one of the first property-testing frameworks, using random genrators.<p>- SmallCheck came later, which enumerates data instead (e.g. testing a Float might use 0, 1, -1, 2, -2, 0.5, -0.5, etc.). That's cute, but QuickCheck tends to exercise more code paths with each input.<p>- LazySmallCheck builds up test data on-demand, using Haskell's pervasive laziness. Tests are run with an error as input: if they pass, we're done; if they fail, we're done; if they trigger the error, they're run again with slightly more-defined inputs. For example, if the input is supposed to be a list, we try again with the two forms of list: empty and "cons" (the arguments to cons are both errors, to begin with). This exercises even more code paths for each input.<p>- LazySmallCheck2012 is a more versatile "update" to LazySmallCheck; in particular, it's able to generate functions.