Skip to main content

shape_vm/feature_tests/
testing_framework_tests.rs

1//! Tests for testing framework features
2//!
3//! This module covers testing framework grammar rules from shape.pest:
4//! - test_def: `test "description" { ... }`
5//! - assert_statement: `assert x == 5;`
6//! - test_setup: `setup { ... }`
7//! - test_teardown: `teardown { ... }`
8//! - test_tag: `@slow test "..." { }`
9//! - expect_statement: `expect(x).toBe(5);`
10//! - should_statement: `x should equal 5;`
11
12use super::{FeatureCategory, FeatureTest};
13
14pub const TESTS: &[FeatureTest] = &[
15    // === Test Definition ===
16    FeatureTest {
17        name: "test_def_basic",
18        covers: &["test_def", "test_body", "test_case", "test_statements"],
19        code: r#"
20            test "basic test suite" {
21                test "should return correct value" {
22                    let x = 42;
23                }
24            }
25            function test() { return 42; }
26        "#,
27        function: "test",
28        category: FeatureCategory::Module,
29        requires_data: false,
30    },
31    FeatureTest {
32        name: "test_def_with_it",
33        covers: &["test_def", "test_case"],
34        code: r#"
35            test "using it keyword" {
36                it "should work with it" {
37                    let y = 10;
38                }
39            }
40            function test() { return 42; }
41        "#,
42        function: "test",
43        category: FeatureCategory::Module,
44        requires_data: false,
45    },
46    // === Assert Statement ===
47    FeatureTest {
48        name: "assert_statement_basic",
49        covers: &["assert_statement", "test_statement"],
50        code: r#"
51            test "assert tests" {
52                test "basic assert" {
53                    assert 1 == 1;
54                }
55            }
56            function test() { return 42; }
57        "#,
58        function: "test",
59        category: FeatureCategory::Module,
60        requires_data: false,
61    },
62    FeatureTest {
63        name: "assert_statement_with_message",
64        covers: &["assert_statement"],
65        code: r#"
66            test "assert with message" {
67                test "named assert" {
68                    assert 1 == 1, "one should equal one";
69                }
70            }
71            function test() { return 42; }
72        "#,
73        function: "test",
74        category: FeatureCategory::Module,
75        requires_data: false,
76    },
77    // === Setup and Teardown ===
78    FeatureTest {
79        name: "test_setup_basic",
80        covers: &["test_setup", "test_body"],
81        code: r#"
82            test "setup example" {
83                setup {
84                    let shared = 100;
85                }
86                test "uses setup" {
87                    let x = 1;
88                }
89            }
90            function test() { return 42; }
91        "#,
92        function: "test",
93        category: FeatureCategory::Module,
94        requires_data: false,
95    },
96    FeatureTest {
97        name: "test_teardown_basic",
98        covers: &["test_teardown", "test_body"],
99        code: r#"
100            test "teardown example" {
101                teardown {
102                    let cleanup = true;
103                }
104                test "with teardown" {
105                    let x = 1;
106                }
107            }
108            function test() { return 42; }
109        "#,
110        function: "test",
111        category: FeatureCategory::Module,
112        requires_data: false,
113    },
114    FeatureTest {
115        name: "test_setup_teardown_combined",
116        covers: &["test_setup", "test_teardown", "test_body"],
117        code: r#"
118            test "full lifecycle" {
119                setup {
120                    let data = 42;
121                }
122                teardown {
123                    let cleanup = true;
124                }
125                test "lifecycle test" {
126                    let x = 1;
127                }
128            }
129            function test() { return 42; }
130        "#,
131        function: "test",
132        category: FeatureCategory::Module,
133        requires_data: false,
134    },
135    // === Test Tags ===
136    FeatureTest {
137        name: "test_tag_single",
138        covers: &["test_tag", "test_tags", "test_case"],
139        code: r#"
140            test "tagged tests" {
141                test "slow test" -> [slow] {
142                    let x = 1;
143                }
144            }
145            function test() { return 42; }
146        "#,
147        function: "test",
148        category: FeatureCategory::Module,
149        requires_data: false,
150    },
151    FeatureTest {
152        name: "test_tag_multiple",
153        covers: &["test_tag", "test_tags"],
154        code: r#"
155            test "multiple tags" {
156                test "integration test" -> [slow, integration, network] {
157                    let x = 1;
158                }
159            }
160            function test() { return 42; }
161        "#,
162        function: "test",
163        category: FeatureCategory::Module,
164        requires_data: false,
165    },
166    FeatureTest {
167        name: "test_tag_string",
168        covers: &["test_tag"],
169        code: r#"
170            test "string tags" {
171                test "with string tag" -> ["custom-tag"] {
172                    let x = 1;
173                }
174            }
175            function test() { return 42; }
176        "#,
177        function: "test",
178        category: FeatureCategory::Module,
179        requires_data: false,
180    },
181    // === Expect Statement ===
182    FeatureTest {
183        name: "expect_to_be",
184        covers: &["expect_statement", "expectation_matcher"],
185        code: r#"
186            test "expect toBe" {
187                test "value comparison" {
188                    expect(42).toBe(42);
189                }
190            }
191            function test() { return 42; }
192        "#,
193        function: "test",
194        category: FeatureCategory::Module,
195        requires_data: false,
196    },
197    FeatureTest {
198        name: "expect_to_equal",
199        covers: &["expect_statement", "expectation_matcher"],
200        code: r#"
201            test "expect toEqual" {
202                test "equality check" {
203                    expect(10).toEqual(10);
204                }
205            }
206            function test() { return 42; }
207        "#,
208        function: "test",
209        category: FeatureCategory::Module,
210        requires_data: false,
211    },
212    FeatureTest {
213        name: "expect_to_be_close_to",
214        covers: &["expect_statement", "expectation_matcher"],
215        code: r#"
216            test "expect toBeCloseTo" {
217                test "float comparison" {
218                    expect(3.14159).toBeCloseTo(3.14, 2);
219                }
220            }
221            function test() { return 42; }
222        "#,
223        function: "test",
224        category: FeatureCategory::Module,
225        requires_data: false,
226    },
227    FeatureTest {
228        name: "expect_to_be_greater_than",
229        covers: &["expect_statement", "expectation_matcher"],
230        code: r#"
231            test "expect toBeGreaterThan" {
232                test "greater comparison" {
233                    expect(10).toBeGreaterThan(5);
234                }
235            }
236            function test() { return 42; }
237        "#,
238        function: "test",
239        category: FeatureCategory::Module,
240        requires_data: false,
241    },
242    FeatureTest {
243        name: "expect_to_be_less_than",
244        covers: &["expect_statement", "expectation_matcher"],
245        code: r#"
246            test "expect toBeLessThan" {
247                test "less comparison" {
248                    expect(3).toBeLessThan(10);
249                }
250            }
251            function test() { return 42; }
252        "#,
253        function: "test",
254        category: FeatureCategory::Module,
255        requires_data: false,
256    },
257    FeatureTest {
258        name: "expect_to_contain",
259        covers: &["expect_statement", "expectation_matcher"],
260        code: r#"
261            test "expect toContain" {
262                test "contains check" {
263                    expect([1, 2, 3]).toContain(2);
264                }
265            }
266            function test() { return 42; }
267        "#,
268        function: "test",
269        category: FeatureCategory::Module,
270        requires_data: false,
271    },
272    FeatureTest {
273        name: "expect_to_be_truthy",
274        covers: &["expect_statement", "expectation_matcher"],
275        code: r#"
276            test "expect toBeTruthy" {
277                test "truthy check" {
278                    expect(true).toBeTruthy();
279                }
280            }
281            function test() { return 42; }
282        "#,
283        function: "test",
284        category: FeatureCategory::Module,
285        requires_data: false,
286    },
287    FeatureTest {
288        name: "expect_to_be_falsy",
289        covers: &["expect_statement", "expectation_matcher"],
290        code: r#"
291            test "expect toBeFalsy" {
292                test "falsy check" {
293                    expect(false).toBeFalsy();
294                }
295            }
296            function test() { return 42; }
297        "#,
298        function: "test",
299        category: FeatureCategory::Module,
300        requires_data: false,
301    },
302    // expect_to_throw removed: throw() builtin removed
303    FeatureTest {
304        name: "expect_to_match_pattern",
305        covers: &[
306            "expect_statement",
307            "expectation_matcher",
308            "test_match_options",
309        ],
310        code: r#"
311            test "expect toMatchPattern" {
312                test "pattern match" {
313                    expect(data).toMatchPattern(hammer, { fuzzy: 0.02 });
314                }
315            }
316            function test() { return 42; }
317        "#,
318        function: "test",
319        category: FeatureCategory::Domain,
320        requires_data: false,
321    },
322    // === Should Statement ===
323    FeatureTest {
324        name: "should_be",
325        covers: &["should_statement", "should_matcher"],
326        code: r#"
327            test "should be" {
328                test "be matcher" {
329                    42 should be 42;
330                }
331            }
332            function test() { return 42; }
333        "#,
334        function: "test",
335        category: FeatureCategory::Module,
336        requires_data: false,
337    },
338    FeatureTest {
339        name: "should_equal",
340        covers: &["should_statement", "should_matcher"],
341        code: r#"
342            test "should equal" {
343                test "equal matcher" {
344                    10 should equal 10;
345                }
346            }
347            function test() { return 42; }
348        "#,
349        function: "test",
350        category: FeatureCategory::Module,
351        requires_data: false,
352    },
353    FeatureTest {
354        name: "should_contain",
355        covers: &["should_statement", "should_matcher"],
356        code: r#"
357            test "should contain" {
358                test "contain matcher" {
359                    [1, 2, 3] should contain 2;
360                }
361            }
362            function test() { return 42; }
363        "#,
364        function: "test",
365        category: FeatureCategory::Module,
366        requires_data: false,
367    },
368    FeatureTest {
369        name: "should_match",
370        covers: &["should_statement", "should_matcher"],
371        code: r#"
372            test "should match" {
373                test "match pattern" {
374                    data should match hammer;
375                }
376            }
377            function test() { return 42; }
378        "#,
379        function: "test",
380        category: FeatureCategory::Domain,
381        requires_data: false,
382    },
383    FeatureTest {
384        name: "should_be_close_to",
385        covers: &["should_statement", "should_matcher"],
386        code: r#"
387            test "should be_close_to" {
388                test "close to matcher" {
389                    3.14159 should be_close_to 3.14 within 0.01;
390                }
391            }
392            function test() { return 42; }
393        "#,
394        function: "test",
395        category: FeatureCategory::Module,
396        requires_data: false,
397    },
398    // === Test Fixtures ===
399    FeatureTest {
400        name: "test_fixture_with_data",
401        covers: &["test_fixture_statement"],
402        code: r#"
403            test "fixture tests" {
404                test "with data fixture" {
405                    with_data([1, 2, 3]) {
406                        let sum = 6;
407                    }
408                }
409            }
410            function test() { return 42; }
411        "#,
412        function: "test",
413        category: FeatureCategory::Module,
414        requires_data: false,
415    },
416    FeatureTest {
417        name: "test_fixture_with_mock",
418        covers: &["test_fixture_statement"],
419        code: r#"
420            test "mock tests" {
421                test "with mock fixture" {
422                    with_mock(fetch, { status: 200 }) {
423                        let result = true;
424                    }
425                }
426            }
427            function test() { return 42; }
428        "#,
429        function: "test",
430        category: FeatureCategory::Module,
431        requires_data: false,
432    },
433];
434
435#[cfg(test)]
436mod tests {
437    use super::*;
438    use std::collections::HashSet;
439
440    #[test]
441    fn test_testing_framework_tests_defined() {
442        assert!(!TESTS.is_empty());
443        // Verify all tests have unique names
444        let names: HashSet<_> = TESTS.iter().map(|t| t.name).collect();
445        assert_eq!(names.len(), TESTS.len(), "All test names should be unique");
446    }
447
448    #[test]
449    fn test_covers_testing_rules() {
450        let all_covered: HashSet<_> = TESTS.iter().flat_map(|t| t.covers.iter()).collect();
451        // Check that key testing framework rules are covered
452        assert!(
453            all_covered.contains(&"test_def"),
454            "Should cover 'test_def' rule"
455        );
456        assert!(
457            all_covered.contains(&"assert_statement"),
458            "Should cover 'assert_statement' rule"
459        );
460        assert!(
461            all_covered.contains(&"test_setup"),
462            "Should cover 'test_setup' rule"
463        );
464        assert!(
465            all_covered.contains(&"test_teardown"),
466            "Should cover 'test_teardown' rule"
467        );
468        assert!(
469            all_covered.contains(&"test_tag"),
470            "Should cover 'test_tag' rule"
471        );
472        assert!(
473            all_covered.contains(&"expect_statement"),
474            "Should cover 'expect_statement' rule"
475        );
476        assert!(
477            all_covered.contains(&"should_statement"),
478            "Should cover 'should_statement' rule"
479        );
480    }
481}