effect-ts
Code
A library for law testing. Test @effect/typeclass and schema laws using fast-check. The typeclass laws implemented are listed here.
Read on for the project introduction or jump to:
Option<A>
testTypeClassLaws
will find the correct typeclass laws and test them. To define the tests required
for the Option
datatype, for example, we need to:
Equivalence<Option<A>>
from an
Equivalence<A>
.
effect-ts
has such a function in the Option
module called
getEquivalence.effect-ts-laws
exports an option
function. It takes an Arbitrary<A>
and return an Arbitrary<Option<A>>
.Order
, are built from
the instance of the underlying type. The effect-ts-laws
export
monoOrder
provides this for the Order
typeclass.The Option
typeclass law test:
import {
Alternative,
Applicative,
Foldable,
getOptionalMonoid,
Monad,
Traversable
} from '@effect/typeclass/data/Option'
import {Option as OP} from 'effect'
import {monoEquivalence, monoOrder, monoSemigroup, option} from 'effect-ts-laws'
import {testTypeclassLaws} from 'effect-ts-laws/vitest'
import {OptionTypeLambda} from 'effect/Option'
describe('@effect/typeclass/data/Option', () => {
testTypeclassLaws<OptionTypeLambda>({
getEquivalence: OP.getEquivalence,
getArbitrary: option,
})({
Alternative,
Applicative,
Equivalence: OP.getEquivalence(monoEquivalence),
Foldable,
Monad,
Monoid: getOptionalMonoid(monoSemigroup),
Order: OP.getOrder(monoOrder),
Traversable,
})
})
What do we get in return to our investment in the three steps above and in the added maintenance costs of this tiny, easy to maintain test?
Good coverage for a freight train full of fault models. Vitest reporter showing
test results for the seventy one typeclass laws relevant to the effect-ts Option
datatype as defined in the test above:
You wrote a new datatype: MyTuple
, and an instance of the effect-ts
Covariant
typeclass. Lets test it for free:
import {Covariant as CO} from '@effect/typeclass'
import {Array as AR} from 'effect'
import {dual} from 'effect/Function'
import {TypeLambda} from 'effect/HKT'
import fc from 'fast-check'
import {testTypeclassLaws} from 'effect-ts-laws/vitest'
describe('MyTuple', () => {
type MyTuple<A> = [A]
interface MyTupleTypeLambda extends TypeLambda {
readonly type: MyTuple<this['Target']>
}
const map: CO.Covariant<MyTupleTypeLambda>['map'] = dual(
2,
<A, B>([a]: MyTuple<A>, ab: (a: A) => B): MyTuple<B> => [ab(a)],
)
const Covariant: CO.Covariant<MyTupleTypeLambda> = {
imap: CO.imap<MyTupleTypeLambda>(map),
map,
}
testTypeclassLaws<MyTupleTypeLambda>({
getEquivalence: AR.getEquivalence,
getArbitrary: fc.tuple,
})({Covariant})
})
fast-check
will try to find a counterexample that breaks the laws. Because
it is quite impossible to find one in this case you should see:
Above you see that eight typeclass laws that were tested:
count = 2
count = 2 + 2
Option
Invariant instance
and run through the identity and composition laws.
count = 2 + 2 + 2
Option
Covariant instance and run through
the identity and composition laws. count = 2 + 2 + 2 + 2
Law testing is property
testing, except the properties
are well known laws. Besides being famous, the laws included here were chosen
because they catch bugs efficiently . If you can identify the laws that should
govern your code, then effect-ts-laws
will help you test them.
For example when implementing instances of effect-ts typeclasses for your
datatype, they must be bound by their
typeclass laws.
effect-ts-laws
exports ready-made tests for these, and with very little work
they can be added to your test suite to reduce the risk your customizations are
unlawful.
Features:
effect-ts
typeclasseseffect-ts
datatype typeclass law tests to serve as self-test, demo, and
to help this remarkable project. See
status for details on what is ready.fast-check
arbitraries for
effect datatypesfast-check
Arbitrary type.fast-check
property testing. For
parameterized type typeclass laws, all functions are randomly generated as
well.getEquivalence
and getArbitrary
.
You can run the project tests online at any of these online sandboxes by opening
a terminal and calling pnpm install && pnpm test-run
. pnpm coverage
will give
you the always 100% coverage report.
Fork
button.The full self-test suite will run in less than 10 seconds on an average desktop, but will take a minute or two to run on the free tiers of the services above.
This matrix shows data-types (in columns) vs. typeclass law tests (in rows). Each intersection of datatype and typeclass can be either: ready (✅), not ready (❌), or not relevant (☐).
Click a datatype (in column header) to open its source code in the effect-ts
project. Click a typeclass name (in row header) to open its laws as defined in
effect-ts-laws
.
README
for the arbitraries exported.README
for the law module.README
at the laws for typeclasses on concrete types.README
at the laws for typeclasses on parameterized types.oneof
arbitrary chosen from built-in instances.