Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/janiczek/elm-minithesis
An Elm port of Minithesis
https://github.com/janiczek/elm-minithesis
elm hypothesis minithesis property-based-testing
Last synced: about 2 months ago
JSON representation
An Elm port of Minithesis
- Host: GitHub
- URL: https://github.com/janiczek/elm-minithesis
- Owner: Janiczek
- License: bsd-3-clause
- Created: 2020-07-21T21:35:34.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2022-12-11T14:44:56.000Z (about 2 years ago)
- Last Synced: 2023-03-11T15:07:17.236Z (almost 2 years ago)
- Topics: elm, hypothesis, minithesis, property-based-testing
- Language: Elm
- Homepage:
- Size: 567 KB
- Stars: 14
- Watchers: 4
- Forks: 1
- Open Issues: 19
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# IMPORTANT:
See also :sparkles:
[`elm-microthesis`](https://github.com/Janiczek/elm-microthesis) :sparkles: (and
its various branches/tags) which is more Elm-idiomatic implementation of the
same ideas. The repo you are currently viewing is a more direct port of the
Python Minithesis idea. Read below.# `elm-minithesis`
`elm-minithesis` is a property-based testing library based on [Minithesis](https://github.com/drmaciver/minithesis), which is the minimal implementation of the core idea of [Hypothesis](https://github.com/HypothesisWorks/hypothesis).
> Read more in the [About](#About) section.
```elm
import Minithesis.Fuzz as Fuzz exposing (Fuzzer)
import Minithesis exposing (Test, TestResult)ints : Fuzzer (List Int)
ints =
Fuzz.list (Fuzz.int 0 10000)findsSmallList : Test (List Int)
findsSmallList =
Minithesis.test "list always sums under 1000 lol" ints <|
\fuzzedList ->
List.sum fuzzedList <= 1000{-| Will fail and shrink to the minimal example:
`( "list always sums under 1000 lol", FailsWith [ 1001 ] )`
-}
result : Int -> TestResult (List Int)
result seed =
Minithesis.run seed findsSmallList{-| Running these tests inside elm-test can be done via functions inside
the Test.Minithesis module
-}
test : Test.Test
test =
Test.Minithesis.mFuzz findsSmallList
```# Tips and tricks
## Examples
Try `Fuzz.example` and `Fuzz.exampleWithSeed` in the REPL for quick
sanity checks of your fuzzers!```elm
import Minithesis.Fuzz as FF.string |> F.exampleWithSeed 0
--> gives 10 examples
["x","I","","6a=U",";W?","uDc",":ei_^~","=Y","-NAT\\QJ","{92H2DI}-(KOc"]F.string |> F.exampleWithSeed 1
--> different seed -> different examples
["KI"," List.sum list <= 1000)
)
-->
( "list always sums under 1000 lol"
, FailsWithShrinks
{ finalRun = [1,1001,0]
, finalValue = [1001]
, history =
[ value = [166,5536,4725,8499,7844,1727], { run = [1,166,1,5536,1,4725,1,8499,1,7844,1,1727,0], shrinkerUsed = "Initial" }
, value = [166,5536], { run = [1,166,1,5536,0], shrinkerUsed = "DeleteChunkAndMaybeDecrementPrevious { size = 8, startIndex = 5 }" }
, value = [5536], { run = [1,5536,0], shrinkerUsed = "DeleteChunkAndMaybeDecrementPrevious { size = 2, startIndex = 1 }" }
, value = [1001], { run = [1,1001,0], shrinkerUsed = "MinimizeChoiceWithBinarySearch { index = 1 }" }
]
}
)
```Paired with some knowledge about which shrinking strategies there are and what
they do, you can sometimes tweak your fuzzers to optimize how they interact with
the shrinking process, allowing them to be shrunk better.(Related: [Hypothesis docs: "Strategies that shrink"](https://github.com/HypothesisWorks/hypothesis/blob/master/guides/strategies-that-shrink.rst))
# About
`elm-minithesis` is a property-based testing library based on [Minithesis](https://github.com/drmaciver/minithesis), which is the minimal implementation of the core idea of [Hypothesis](https://github.com/HypothesisWorks/hypothesis).
Hypothesis itself is a Python testing library for property-based testing. What
sets it apart is its underlying implementation: instead of working on the
generated values themselves (defining shrinkers on these values, eg. saying that
a Bool will shrink from `True` to `[False]` and from `False` to `[]`), it
remembers the underlying random "dice rolls" that were used to generate the
values, and it shrinks *those*.```elm
-- "type-based shrinking"
-- (QuickCheck and most other property-based testing libraries, including elm-test)
shrink : a -> LazyList a -- has to be defined for each fuzzed type,
-- doesn't shrink by default-- "integrated shrinking"
-- (Hypothesis, jqwik, elm-minithesis :) )
shrink : List Int -> LazyList (List Int) -- shrinks all fuzzers automatically,
-- can't be configured
```A very cool consequence of the above is is that it mostly sidesteps the issue
most other property-based testing libraries have: `andThen` (monadic bind). More
specifically, QuickCheck-like libraries either don't expose `andThen` at all (as
is the case with Elm), or struggle with making the shrunk values satisfy the
same invariants the `andThen`-generated values do. Hypothesis instead shrinks
the underlying "dice roll" history and generates a new value from that, so
its values satisfy the invariants out of the box even if using `andThen`!(Source: [Hypothesis blog: "Integrated vs type based shrinking"](https://hypothesis.works/articles/integrated-shrinking/))
# Community
There is a small piece of internet dedicated to `elm-minithesis`: [the
`#elm-minithesis` channel on Incremental Elm
Discord](https://discord.gg/PC7Ckpg). Come join and hear about updates first!The original discussion around `elm-minithesis` happened on the [Elm
Discourse](https://discourse.elm-lang.org/t/elm-minithesis-shrinking-without-compromises/6071/).