Skip to content

Commit bb60b6c

Browse files
author
Drew Dolgert
authored
Merge pull request #19 from adolgert/docs/explain-up-front
Docs/explain up front
2 parents 5ba1eea + 3e99284 commit bb60b6c

13 files changed

+373
-80
lines changed

docs/make.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ makedocs(;
1717
"Home" => "index.md",
1818
"Manual" => [
1919
"Guide" => "man/guide.md",
20+
"Examples" => "man/examples.md",
21+
"Testing Methods" => "man/methods.md",
2022
"Engines" => "man/engines.md",
21-
"Usage" => "man/usage.md"
23+
"IPOG" => "man/ipog.md"
2224
],
2325
"Reference" => "reference.md",
2426
"Contributing" => "contributing.md"

docs/src/contributing.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ and my email is listed.
1212

1313
## Branch process
1414

15-
- The `main` branch is for development.
16-
- Releases go to `release`.
15+
The trunk is called `main`. I use PRs from branches or other repos to main.
16+
If this project needs more than that, let's discuss it.
1717

1818
## Conduct
1919

20-
Let's follow the contributor covenant.
20+
Let's follow the [Contributor Covenant Code of Conduct](@ref).

docs/src/index.md

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11

22
# UnitTestDesign
33

4-
A [Julia](http://julialang.org) package to generate test cases for unit tests.
5-
This provides **all-pairs** and higher-order algorithms.
4+
A [Julia](http://julialang.org) package to generate parameters for unit tests
5+
and test data for unit tests. You tell it possible values for each parameter of a function,
6+
and it selects combinations of parameters that are most likely to find
7+
problems in that function.
68

7-
* All-pairs, all-triples, and higher-order coverage of test cases.
9+
* [All-pairs](http://pairwise.org/), all-triples, and higher-order coverage of test cases.
810
* Combinatorial excursions from a base test case.
911
* Convenient ways to avoid uninteresting parameter combinations,
1012
add necessary test cases, and increase coverage for subsets of parameters.
@@ -16,24 +18,7 @@ pkg> add https://github.com/adolgert/UnitTestDesign.jl
1618
```
1719

1820
## Description
19-
20-
If we have a function-under-test that takes four arguments, each of which
21-
can have three possible values, then there are 81 possible combinations of
22-
inputs. The [`all_pairs`](@ref) function selects 10 inputs that contain every pair
23-
parameter values at least once.
24-
25-
```@repl
26-
using UnitTestDesign
27-
test_cases = all_pairs(
28-
[1, 2, 3], ["low", "mid" ,"high"], [1.0, 3.7, 4.9], [:greedy, :relax, :optim])
29-
```
30-
31-
Each item in this array is a set of parameters for unit testing the function.
32-
This test set is an example of all-pairs because we can pick any two parameters (second and fourth),
33-
pick any of the values for those parameters ("mid" and :relax), and find
34-
them in one of the test cases (the 2nd one).
35-
36-
Use a test set for unit testing:
21+
Write a unit test using the [`all_pairs`](@ref) function.
3722

3823
```julia
3924
test_set = all_pairs(
@@ -44,6 +29,16 @@ for test_case in test_set
4429
@test test_result == known_result(test_case)
4530
end
4631
```
47-
4832
This package doesn't help write the code that knows what the
4933
[correct test result](https://en.wikipedia.org/wiki/Test_oracle) should be.
34+
35+
In order to test every possible input to the function above, you would
36+
need 81 tests, but this generates 10 tests that are more likely to find
37+
most faults because they include every combination of each pair of parameter
38+
values.
39+
40+
```@repl
41+
using UnitTestDesign
42+
test_cases = all_pairs(
43+
[1, 2, 3], ["low", "mid" ,"high"], [1.0, 3.7, 4.9], [:greedy, :relax, :optim])
44+
```

docs/src/man/code_of_conduct.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
2+
# Contributor Covenant Code of Conduct
3+
4+
## Our Pledge
5+
6+
We as members, contributors, and leaders pledge to make participation in our
7+
community a harassment-free experience for everyone, regardless of age, body
8+
size, visible or invisible disability, ethnicity, sex characteristics, gender
9+
identity and expression, level of experience, education, socio-economic status,
10+
nationality, personal appearance, race, religion, or sexual identity
11+
and orientation.
12+
13+
We pledge to act and interact in ways that contribute to an open, welcoming,
14+
diverse, inclusive, and healthy community.
15+
16+
## Our Standards
17+
18+
Examples of behavior that contributes to a positive environment for our
19+
community include:
20+
21+
* Demonstrating empathy and kindness toward other people
22+
* Being respectful of differing opinions, viewpoints, and experiences
23+
* Giving and gracefully accepting constructive feedback
24+
* Accepting responsibility and apologizing to those affected by our mistakes,
25+
and learning from the experience
26+
* Focusing on what is best not just for us as individuals, but for the
27+
overall community
28+
29+
Examples of unacceptable behavior include:
30+
31+
* The use of sexualized language or imagery, and sexual attention or
32+
advances of any kind
33+
* Trolling, insulting or derogatory comments, and personal or political attacks
34+
* Public or private harassment
35+
* Publishing others' private information, such as a physical or email
36+
address, without their explicit permission
37+
* Other conduct which could reasonably be considered inappropriate in a
38+
professional setting
39+
40+
## Enforcement Responsibilities
41+
42+
Community leaders are responsible for clarifying and enforcing our standards of
43+
acceptable behavior and will take appropriate and fair corrective action in
44+
response to any behavior that they deem inappropriate, threatening, offensive,
45+
or harmful.
46+
47+
Community leaders have the right and responsibility to remove, edit, or reject
48+
comments, commits, code, wiki edits, issues, and other contributions that are
49+
not aligned to this Code of Conduct, and will communicate reasons for moderation
50+
decisions when appropriate.
51+
52+
## Scope
53+
54+
This Code of Conduct applies within all community spaces, and also applies when
55+
an individual is officially representing the community in public spaces.
56+
Examples of representing our community include using an official e-mail address,
57+
posting via an official social media account, or acting as an appointed
58+
representative at an online or offline event.
59+
60+
## Enforcement
61+
62+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
63+
reported to the community leaders responsible for enforcement at
64+
[INSERT CONTACT METHOD].
65+
All complaints will be reviewed and investigated promptly and fairly.
66+
67+
All community leaders are obligated to respect the privacy and security of the
68+
reporter of any incident.
69+
70+
## Enforcement Guidelines
71+
72+
Community leaders will follow these Community Impact Guidelines in determining
73+
the consequences for any action they deem in violation of this Code of Conduct:
74+
75+
### 1. Correction
76+
77+
**Community Impact**: Use of inappropriate language or other behavior deemed
78+
unprofessional or unwelcome in the community.
79+
80+
**Consequence**: A private, written warning from community leaders, providing
81+
clarity around the nature of the violation and an explanation of why the
82+
behavior was inappropriate. A public apology may be requested.
83+
84+
### 2. Warning
85+
86+
**Community Impact**: A violation through a single incident or series
87+
of actions.
88+
89+
**Consequence**: A warning with consequences for continued behavior. No
90+
interaction with the people involved, including unsolicited interaction with
91+
those enforcing the Code of Conduct, for a specified period of time. This
92+
includes avoiding interactions in community spaces as well as external channels
93+
like social media. Violating these terms may lead to a temporary or
94+
permanent ban.
95+
96+
### 3. Temporary Ban
97+
98+
**Community Impact**: A serious violation of community standards, including
99+
sustained inappropriate behavior.
100+
101+
**Consequence**: A temporary ban from any sort of interaction or public
102+
communication with the community for a specified period of time. No public or
103+
private interaction with the people involved, including unsolicited interaction
104+
with those enforcing the Code of Conduct, is allowed during this period.
105+
Violating these terms may lead to a permanent ban.
106+
107+
### 4. Permanent Ban
108+
109+
**Community Impact**: Demonstrating a pattern of violation of community
110+
standards, including sustained inappropriate behavior, harassment of an
111+
individual, or aggression toward or disparagement of classes of individuals.
112+
113+
**Consequence**: A permanent ban from any sort of public interaction within
114+
the community.
115+
116+
## Attribution
117+
118+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
119+
version 2.0, available at
120+
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
121+
122+
Community Impact Guidelines were inspired by
123+
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
124+
125+
For answers to common questions about this code of conduct, see the FAQ at
126+
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
127+
at [https://www.contributor-covenant.org/translations][translations].
128+
129+
[homepage]: https://www.contributor-covenant.org
130+
[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
131+
[Mozilla CoC]: https://github.com/mozilla/diversity
132+
[FAQ]: https://www.contributor-covenant.org/faq
133+
[translations]: https://www.contributor-covenant.org/translations
134+

docs/src/man/examples.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Examples
2+
3+
## Test parameter generation
4+
5+
For a small test set, generate tests is quick.
6+
7+
```julia
8+
test_set = all_pairs(
9+
[(-3, -2), (2, 3), (-2, 3), (4.999, 5), (0, 1e7)],
10+
[0.1, 0.01, 0.001],
11+
[:RungeKutta, :Midpoint]
12+
)
13+
for test_case in test_set
14+
a, b = test_case[1]
15+
result = custom_integrate(a, b, test_case[2:end]...)
16+
@test result == compare_with_symbolic_integration(a, b)
17+
end
18+
```
19+
20+
21+
## Save larger test suites instead of regenerating
22+
23+
For a larger test set, it can be worthwhile to make test suites
24+
and save them.
25+
```julia
26+
wide_test = all_triples(fill(1:4, 30)...)
27+
JLD.save("test_artifact.jld", "wide_test", wide_test)
28+
```
29+
These could then be made available for testing through
30+
[Pkg.Artifacts](https://julialang.github.io/Pkg.jl/v1.5/artifacts/).
31+
32+
33+
## Test data generation
34+
35+
We use combinatoric testing because it finds all code paths. Code
36+
paths are lines of code chosen by the same if-then decision.
37+
Some code has few code paths but many branches. For instance,
38+
`data_frame = all_data_frame[data_frame[:, :time] > 10]` has two
39+
branches, one for times less than ten and one for times greater than ten.
40+
41+
This library will create test data as easily as it creates test cases.
42+
43+
```@example
44+
using UnitTestDesign # hide
45+
using DataFrames
46+
names = ["time", "event", "who", "location"]
47+
at = all_triples([0.1, 5.1, 10.9], [:infect, :recover], [10, 11], ["forest", "home"])
48+
DataFrame(Dict(names[i] => [row[i] for row in at] for i in 1:length(names))...)
49+
```
50+
51+
## Excursions
52+
53+
If you want to start with a single test that you know is a common
54+
way to call a function, then an excursion can generate variations
55+
around that common way. It picks one parameter and walks through
56+
its values. Then another. If you choose a pair-wise excursion, it
57+
walks all pairs away from the initial value.
58+
59+
```@example
60+
using UnitTestDesign # hide
61+
values_excursion([1, 2], [true, false], ["c", "b", "a"])
62+
```
63+
64+
## Filtering a factorial
65+
66+
The full-factorial test generates every possible test. If some combinations
67+
of parameters aren't interesting or allowed for a function, you can
68+
exclude them by using an extra argument.
69+
```@example
70+
using UnitTestDesign # hide
71+
disallow = (a, b, c) -> b == 7 && c == false
72+
full_factorial([1, 2, 3], [7, 8], [true, false]; disallow = disallow)
73+
```

docs/src/man/guide.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
- [`full_factorial`](@ref): Generates all combinations of parameters, filtering
2323
those that aren't permitted.
2424

25-
## Same interface for all of test generators
25+
## Same interface for all test generators
2626

2727
### Increase coverage for subsets of parameters
2828

@@ -34,7 +34,8 @@ to request that the subset of parameters have greater coverage.
3434
For instance, this requrests that the first, third, and fourth parameters
3535
have 3-way coverage, meaning full-factorial, while the second parameter has
3636
only 2-way coverage. This is more meaningful when there are lots of parameters.
37-
```julia
37+
```@example
38+
using UnitTestDesign # hide
3839
test_set = all_pairs(
3940
[1, 2, 3], ["low", "mid" ,"high"], [1.0, 3.7, 4.9], [:greedy, :relax, :optim];
4041
wayness = Dict(3 => [[1, 3, 4]])
@@ -48,6 +49,7 @@ together, should be covered at the given level. This means that, were you to hav
4849
parameters, you could request that parameters `[3:6]` and parameters `[25:30]` be
4950
covered with triples.
5051
```julia
52+
array_of_forty_parameters = fill(1:4, 40)
5153
test_set = all_pairs(
5254
array_of_forty_parameters...;
5355
wayness = Dict(3 => [[3:6], [25:30]])
@@ -61,11 +63,12 @@ Keep the test engine from making tests that aren't allowed for
6163
your function. Pass it a filter function, one that returns `true`
6264
whenever a parameter combinations is forbidden.
6365

64-
```julia
66+
```@example
67+
using UnitTestDesign # hide
6568
disallow(n, level, value, kind) = level == "high" && kind == :optim
6669
test_set = all_pairs(
6770
[1, 2, 3], ["low", "mid" ,"high"], [1.0, 3.7, 4.9], [:greedy, :relax, :optim];
68-
filter = disallow
71+
disallow = disallow
6972
)
7073
```
7174

@@ -76,7 +79,8 @@ If there are particular tests that must be run, these already include
7679
some of the tuples that should be covered. You can pass the must-run
7780
test cases, and they will be included among the test cases.
7881

79-
```julia
82+
```@example
83+
using UnitTestDesign # hide
8084
must_test = [[1, "mid", 3.7, :relax], [1, "mid", 4.9, :relax]]
8185
test_cases = all_pairs(
8286
[1, 2, 3], ["low", "mid" ,"high"], [1.0, 3.7, 4.9], [:greedy, :relax, :optim];

0 commit comments

Comments
 (0)