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 + 2Option Covariant instance and run through
the identity and composition laws. count = 2 + 2 + 2 + 2Law 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.