Verified Commit b9586b80 authored by Camil Staps's avatar Camil Staps 🚀

Fix readme formatting

parent 906de3a6
Pipeline #13809 failed with stage
in 54 seconds
......@@ -8,73 +8,73 @@ The properties to test are described in [CleanDoc][] blocks: comments above
function types. This works as follows:
- On the module documentation block, add a `@property-bootstrap` field. This
field should contain the 'header' of the generated test program: required
imports and helper definitions. The programmer must not add a module header
(`definition module ...`) and does not need to import Gast modules or the
module under test itself.
field should contain the 'header' of the generated test program: required
imports and helper definitions. The programmer must not add a module header
(`definition module ...`) and does not need to import Gast modules or the
module under test itself.
- On each function to test, add one or more `@property` fields to the docblock.
This property for now always starts with `A.`, followed by a number of
parameters and their types. The first line ends with a colon `:`. The
implementation of the property follows on the next line(s). For example:
This property for now always starts with `A.`, followed by a number of
parameters and their types. The first line ends with a colon `:`. The
implementation of the property follows on the next line(s). For example:
```clean
/**
* @property member_correct: A.x :: a; xs :: [a]:
* member x (fromList xs) <==> isMember x xs
*/
member :: !a !(Set a) -> Bool | < a
```
```clean
/**
* @property member_correct: A.x :: a; xs :: [a]:
* member x (fromList xs) <==> isMember x xs
*/
member :: !a !(Set a) -> Bool | < a
```
Note that one can use Gast's `<==>` here without import, nor does one need to
import the module itself for `member` (and `fromList`). However, `isMember`
requires `import StdList` in the `@property-bootstrap` of the module.
Note that one can use Gast's `<==>` here without import, nor does one need to
import the module itself for `member` (and `fromList`). However, `isMember`
requires `import StdList` in the `@property-bootstrap` of the module.
It is possible to use multiple lines for the implementation of the property.
`testproperties` will guess the right indentation level.
It is possible to use multiple lines for the implementation of the property.
`testproperties` will guess the right indentation level.
- When parameters in `@property` fields contain type variables, the programmer
is required to suggest types to instantiate these variables with when
testing &mdash; otherwise, how would Gast be able to generate test cases?
This can be done with `@property-test-with`, either locally on the function
docblock or globally on the module docblock. For example:
```clean
/**
* @property-test-with a = Int
* @property-test-with a = Real
*/
```
For all relevant tests using the type variable `a`, two versions will be
generated: one with `Int` and one with `Real`. When multiple type variables
are used, all combinations are tested.
is required to suggest types to instantiate these variables with when
testing &mdash; otherwise, how would Gast be able to generate test cases?
This can be done with `@property-test-with`, either locally on the function
docblock or globally on the module docblock. For example:
```clean
/**
* @property-test-with a = Int
* @property-test-with a = Real
*/
```
For all relevant tests using the type variable `a`, two versions will be
generated: one with `Int` and one with `Real`. When multiple type variables
are used, all combinations are tested.
- Sometimes, Gast's generic test generation method is not very useful. This is
for instance the case with types for which automatically generated values are
not 'valid'.
Take `Set a` as an example. It is possible to write tests on `[a]` instead,
then in every test use `fromList :: [a] -> Set a` to get the set. However,
this is not very modular, and also clutters up the properties.
What you can do instead is writing tests as you would normally do,
quantifying over `Set a` in the property signature, and then add a
`@property-test-generator` to the module. This field tells the test generator
how to generate values of a certain type. An example is:
```clean
/**
* @property-test-generator [a] -> Set a | < a
* gen xs = fromList xs
*/
```
Currently, only generators with arity 1 are supported (but this can be worked
around using a tuple or an auxiliary data type in the `@property-bootstrap`).
When the generator has class constraints, you are expected to resolve them
yourself by providing the required instances, depending on the type variable
instantiations.
for instance the case with types for which automatically generated values are
not 'valid'.
Take `Set a` as an example. It is possible to write tests on `[a]` instead,
then in every test use `fromList :: [a] -> Set a` to get the set. However,
this is not very modular, and also clutters up the properties.
What you can do instead is writing tests as you would normally do,
quantifying over `Set a` in the property signature, and then add a
`@property-test-generator` to the module. This field tells the test generator
how to generate values of a certain type. An example is:
```clean
/**
* @property-test-generator [a] -> Set a | < a
* gen xs = fromList xs
*/
```
Currently, only generators with arity 1 are supported (but this can be worked
around using a tuple or an auxiliary data type in the `@property-bootstrap`).
When the generator has class constraints, you are expected to resolve them
yourself by providing the required instances, depending on the type variable
instantiations.
[Gast]: https://gitlab.science.ru.nl/clean-and-itasks/gast
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment