Skip to content

Commit 5362a86

Browse files
committed
Make the proc macro an experimentation thing
1 parent 3307ad7 commit 5362a86

File tree

1 file changed

+102
-89
lines changed

1 file changed

+102
-89
lines changed

text/0000-custom-test-frameworks.md

Lines changed: 102 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,79 @@ crate developers invoke various test-like steps using the framework.
6868

6969
## Procedural macro for a new test framework
7070

71-
A test framework is like a whole-crate procedural
72-
macro that is evaluated after all other macros in the target crate have
73-
been evaluated. It is passed the `TokenStream` for every element in the
71+
A test framework is like a procedural macro that is evaluated after all other macros in the target
72+
crate have been evaluated. The exact mechanism is left up to the experimentation phase, however we
73+
have some proposals at the end of this RFC.
74+
75+
76+
A crate may only define a single framework.
77+
78+
## Cargo integration
79+
80+
Alternative frameworks need to integrate with cargo.
81+
In particular, when crate `a` uses a crate `b` which provides an
82+
framework, `a` needs to be able to specify when `b`'s framework
83+
should be used. Furthermore, cargo needs to understand that when
84+
`b`'s framework is used, `b`'s dependencies must also be linked.
85+
86+
Crates which define a test framework must have a `[testing.framework]`
87+
key in their `Cargo.toml`. They cannot be used as regular dependencies.
88+
This section works like this:
89+
90+
```rust
91+
[testing.framework]
92+
kind = "test" # or bench
93+
```
94+
95+
`lib` specifies if the `--lib` mode exists for this framework by default,
96+
and `folders` specifies which folders the framework applies to. Both can be overridden
97+
by consumers.
98+
99+
`single-target` indicates that only a single target can be run with this
100+
framework at once (some tools, like cargo-fuzz, run forever, and so it
101+
does not make sense to specify multiple targets).
102+
103+
Crates that wish to *use* a custom test framework, do so by including a framework
104+
under a new `[[testing.frameworks]]` section in their
105+
`Cargo.toml`:
106+
107+
```toml
108+
[[testing.frameworks]]
109+
provider = { quickcheck = "1.0" }
110+
```
111+
112+
This pulls in the framework from the "quickcheck" crate. By default, the following
113+
framework is defined:
114+
115+
```toml
116+
[[testing.frameworks]]
117+
provider = { test = "1.0" }
118+
```
119+
120+
(We may define a default framework for bench in the future)
121+
122+
Declaring a test framework will replace the existing default one. You cannot declare
123+
more than one test or bench framework.
124+
125+
To invoke a particular framework, a user invokes `cargo test` or `cargo bench`. Any additional
126+
arguments are passed to the testing binary. By convention, the first position argument should allow
127+
filtering which targets (tests/benchmarks/etc.) are run.
128+
129+
## To be designed
130+
131+
This contains things which we should attempt to solve in the course of this experiment, for which this eRFC
132+
does not currently provide a concrete proposal.
133+
134+
## Procedural macro design
135+
136+
137+
We have a bunch of concrete proposals here, but haven't yet chosen one.
138+
139+
### main() function generation with test collector
140+
141+
One possible design is to have a proc macro that simply generates `main()`
142+
143+
It is passed the `TokenStream` for every element in the
74144
target crate that has a set of attributes the test framework has
75145
registered interest in. For example, to declare a test framework
76146
called `mytest`:
@@ -146,91 +216,7 @@ all their parent modules public). `#[test]` and `#[bench]` items will only exist
146216
with `--cfg test` (or bench), which is automatically set when running tests.
147217

148218

149-
A crate may only define a single framework.
150-
151-
## Cargo integration
152-
153-
Alternative frameworks need to integrate with cargo.
154-
In particular, when crate `a` uses a crate `b` which provides an
155-
framework, `a` needs to be able to specify when `b`'s framework
156-
should be used. Furthermore, cargo needs to understand that when
157-
`b`'s framework is used, `b`'s dependencies must also be linked.
158-
159-
Crates which define a test framework must have a `[testing.framework]`
160-
key in their `Cargo.toml`. They cannot be used as regular dependencies.
161-
This section works like this:
162-
163-
```rust
164-
[testing.framework]
165-
kind = "test" # or bench
166-
```
167-
168-
`lib` specifies if the `--lib` mode exists for this framework by default,
169-
and `folders` specifies which folders the framework applies to. Both can be overridden
170-
by consumers.
171-
172-
`single-target` indicates that only a single target can be run with this
173-
framework at once (some tools, like cargo-fuzz, run forever, and so it
174-
does not make sense to specify multiple targets).
175-
176-
Crates that wish to *use* a custom test framework, do so by including a framework
177-
under a new `[[testing.frameworks]]` section in their
178-
`Cargo.toml`:
179-
180-
```toml
181-
[[testing.frameworks]]
182-
provider = { quickcheck = "1.0" }
183-
```
184-
185-
This pulls in the framework from the "quickcheck" crate. By default, the following
186-
framework is defined:
187-
188-
```toml
189-
[[testing.frameworks]]
190-
provider = { test = "1.0" }
191-
```
192-
193-
(We may define a default framework for bench in the future)
194-
195-
Declaring a test framework will replace the existing default one. You cannot declare
196-
more than one test or bench framework.
197-
198-
To invoke a particular framework, a user invokes `cargo test` or `cargo bench`. Any additional
199-
arguments are passed to the testing binary. By convention, the first position argument should allow
200-
filtering which targets (tests/benchmarks/etc.) are run.
201-
202-
## To be designed
203-
204-
This contains things which we should attempt to solve in the course of this experiment, for which this eRFC
205-
does not currently provide a concrete proposal.
206-
207-
### Standardizing the output
208-
209-
We should probably provide a crate with useful output formatters and stuff so that if test harnesses desire, they can
210-
use the same output formatting as a regular test. This also provides a centralized location to standardize things
211-
like json output and whatnot.
212-
213-
@killercup is working on a proposal for this which I will try to work in.
214-
215-
# Drawbacks
216-
[drawbacks]: #drawbacks
217-
218-
- This adds more sections to `Cargo.toml`.
219-
- This complicates the execution path for cargo, in that it now needs
220-
to know about testing frameworks.
221-
- Flags and command-line parameters for test and bench will now vary
222-
between testing frameworks, which may confuse users as they move
223-
between crates.
224-
225-
# Rationale and alternatives
226-
[alternatives]: #alternatives
227-
228-
We could stabilize `#[bench]` and extend libtest with setup/teardown and
229-
other requested features. This would complicate the in-tree libtest,
230-
introduce a barrier for community contributions, and discourage other
231-
forms of testing or benchmarking.
232-
233-
## Alternative procedural macro
219+
### Whole-crate procedural macro
234220

235221
An alternative proposal was to expose an extremely general whole-crate proc macro:
236222

@@ -266,7 +252,7 @@ these tools usually operate at a different layer of abstraction so it might not
266252
A major drawback of this proposal is that it is very general, and perhaps too powerful. We're currently using the
267253
more focused API in the eRFC, and may switch to this during experimentation if a pressing need crops up.
268254

269-
## Alternative procedural macro with minimal compiler changes
255+
### Alternative procedural macro with minimal compiler changes
270256

271257
The above proposal can be made even more general, minimizing the impact on the compiler.
272258

@@ -289,6 +275,33 @@ pub fn harness(crate: TokenStream) -> TokenStream {
289275
The cargo functionality will basically compile the file with the right dependencies
290276
and `--attribute=your_crate::harness`.
291277

278+
279+
### Standardizing the output
280+
281+
We should probably provide a crate with useful output formatters and stuff so that if test harnesses desire, they can
282+
use the same output formatting as a regular test. This also provides a centralized location to standardize things
283+
like json output and whatnot.
284+
285+
@killercup is working on a proposal for this which I will try to work in.
286+
287+
# Drawbacks
288+
[drawbacks]: #drawbacks
289+
290+
- This adds more sections to `Cargo.toml`.
291+
- This complicates the execution path for cargo, in that it now needs
292+
to know about testing frameworks.
293+
- Flags and command-line parameters for test and bench will now vary
294+
between testing frameworks, which may confuse users as they move
295+
between crates.
296+
297+
# Rationale and alternatives
298+
[alternatives]: #alternatives
299+
300+
We could stabilize `#[bench]` and extend libtest with setup/teardown and
301+
other requested features. This would complicate the in-tree libtest,
302+
introduce a barrier for community contributions, and discourage other
303+
forms of testing or benchmarking.
304+
292305
# Unresolved questions
293306
[unresolved]: #unresolved-questions
294307

0 commit comments

Comments
 (0)