1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! A lightweight library for defining behavior-driven development (BDD) style
//! tests in external files and running them with `cargo test`.
//!
//! To write a test:
//!
//! 1. Implement a [`Handler`] that interprets [`Background`] and [`Example`]
//! sections defined in your spec file.
//! 2. Write a test that calls [`run`] with a `Handler` instance and a path that
//! points to a spec file. You can also use [`glob_test`] to derive one such
//! test for each spec file in a given folder (including subfolders).
//!
//! # Example
//!
//! Here is a minimal example:
//!
//! ```
//! use spectest;
//!
//! struct MevalHandler<'a> {
//! ctx: meval::Context<'a>,
//! }
//!
//! impl<'a> MevalHandler<'a> {
//! fn new() -> Self {
//! Self {
//! ctx: meval::Context::new(),
//! }
//! }
//! }
//!
//! impl<'a> spectest::Handler for MevalHandler<'a> {
//! type Error = String;
//!
//! fn example(&mut self, example: &mut spectest::Example) -> Result<(), Self::Error> {
//! let Some(input) = example.when.get("input") else {
//! let msg = format!("missing `input` definition in the 'When' spec");
//! return Err(msg);
//! };
//! let input = match input.parse::<meval::Expr>() {
//! Ok(expr) => expr,
//! Err(err) => {
//! let msg = format!("cannot parse `input` expression `{input}`: {err}");
//! return Err(msg);
//! }
//! };
//!
//! match input.eval_with_context(self.ctx.clone()) {
//! Ok(value) => {
//! example.then.insert("result", value.to_string() + "\n");
//! }
//! Err(err) => {
//! let msg = format!("cannot evaluate expression: {err}\n");
//! example.then.insert("result", msg);
//! }
//! }
//!
//! Ok(())
//! }
//! }
//!
//! #[spectest::glob_test("testdata/integration/**/*.md")]
//! fn test_meval(path: &str) {
//! let mut handler = MevalHandler::new();
//! spectest::run(path, &mut handler);
//! }
//! ```
//!
//! Assuming that the `testdata/integration` folder contains a single called
//! `calculator.md`, one can run the test against this file as follows:
//!
//! ```bash
//! # Expand the prefix to narrow the set of tested spec files
//! cargo test test_meval_
//! ```
//!
//! It is also possible to mass-rewrite failing tests after fixing/updating the
//! behavior of the `meval` library under test as follows
//! ```bash
//! REWRITE_SPECS=true cargo test test_calculator
//! ```
//!
//! For a more elaborated version that also updates the evaluation context
//! depending on the currently active [`Background`] sections, see the
//! `test/integration.rs` in the source repository.
use Range;
use Event;
pub use ;
pub use glob_test;
// Common private helper types
// ===========================
type Token<'input> = ;
type Tokens<'a, 'input> = &'a mut ;
/// Project the `event` component a `token`.
/// Project the `span` component a `token`.
/// Print a tokens sequence for debugging purposes.
pub