@@ -5,7 +5,7 @@ Property-based testing for Yog graph algorithms using `qcheck` v1.0.4.
55## Test Statistics
66
77| Metric | Count |
8- | --------| -------|
8+ | -------- | ------- |
99| Total tests | 950 |
1010| Property tests | 34 |
1111| Basic properties | 12 |
@@ -20,18 +20,18 @@ gleam test
2020
2121## Test Files
2222
23- | File | Lines | Purpose |
24- | ------| -------| --------- |
25- | ` test/yog/property_tests.gleam ` | 462 | Basic structural properties |
26- | ` test/yog/aggressive_property_tests.gleam ` | 216 | Edge cases and boundary conditions |
27- | ` test/yog/algorithm_property_tests.gleam ` | 466 | Algorithm correctness and cross-validation |
23+ | File | Purpose |
24+ | ------ | --------- |
25+ | ` test/yog/property_tests.gleam ` | Basic structural properties |
26+ | ` test/yog/aggressive_property_tests.gleam ` | Edge cases and boundary conditions |
27+ | ` test/yog/algorithm_property_tests.gleam ` | Algorithm correctness and cross-validation |
2828
2929## Category 1: Structural Properties
3030
3131### Graph Transformations
3232
3333| # | Property | Test Function | Rationale | Status |
34- | ---| ----------| ---------------| -----------| --------|
34+ | --- | ---------- | --------------- | ----------- | -------- |
3535| 1 | Transpose is involutive: ` transpose(transpose(G)) = G ` | ` transpose_involutive_test() ` | Validates O(1) transpose implementation used by SCC algorithms | ✅ |
3636| 2 | Edge count consistency | ` edge_count_consistency_test() ` | Ensures graph statistics match actual edge storage | ✅ |
3737| 3 | Undirected graphs are symmetric | ` undirected_symmetry_test() ` | For undirected graphs, every edge appears in both directions | ✅ |
@@ -40,7 +40,7 @@ gleam test
4040### Data Transformations
4141
4242| # | Property | Test Function | Rationale | Status |
43- | ---| ----------| ---------------| -----------| --------|
43+ | --- | ---------- | --------------- | ----------- | -------- |
4444| 5 | ` map_nodes ` preserves structure | ` map_nodes_preserves_structure_test() ` | Node transformations don't alter graph topology | ✅ |
4545| 6 | ` map_edges ` preserves structure | ` map_edges_preserves_structure_test() ` | Edge transformations don't alter graph topology | ✅ |
4646| 7 | ` filter_nodes ` removes incident edges | ` filter_nodes_removes_incident_edges_test() ` | No dangling edge references after node removal | ✅ |
@@ -49,21 +49,21 @@ gleam test
4949### Operations
5050
5151| # | Property | Test Function | Rationale | Status |
52- | ---| ----------| ---------------| -----------| --------|
52+ | --- | ---------- | --------------- | ----------- | -------- |
5353| 9 | Add/remove edge (directed) | ` add_remove_edge_inverse_directed_test() ` | Edge operations are inverse for directed graphs | ✅ |
5454| 10 | Add/remove edge (undirected) | ` add_remove_edge_inverse_undirected_test() ` | Fully removes both directions (v4.x) | ✅ |
5555
5656### Traversals
5757
5858| # | Property | Test Function | Rationale | Status |
59- | ---| ----------| ---------------| -----------| --------|
59+ | --- | ---------- | --------------- | ----------- | -------- |
6060| 11 | BFS produces no duplicates | ` traversal_no_duplicates_bfs_test() ` | Breadth-first search visits each node once | ✅ |
6161| 12 | DFS produces no duplicates | ` traversal_no_duplicates_dfs_test() ` | Depth-first search visits each node once, even with cycles | ✅ |
6262
6363## Category 2: Edge Cases
6464
6565| # | Case | Test Function | Rationale | Status |
66- | ---| ------| ---------------| -----------| --------|
66+ | --- | ------ | --------------- | ----------- | -------- |
6767| 1 | Empty graphs | ` empty_graph_edge_count_test() ` , ` empty_graph_transpose_test() ` | Operations on graphs with no nodes/edges | ✅ |
6868| 2 | Self-loops (directed) | ` self_loop_directed_test() ` | Node pointing to itself in directed graph | ✅ |
6969| 3 | Self-loops (undirected) | ` self_loop_undirected_test() ` | Node pointing to itself in undirected graph | ✅ |
@@ -79,15 +79,15 @@ gleam test
7979### Cross-Validation
8080
8181| # | Property | Test Function | Rationale | Status |
82- | ---| ----------| ---------------| -----------| --------|
82+ | --- | ---------- | --------------- | ----------- | -------- |
8383| 1 | Tarjan SCC = Kosaraju SCC | ` scc_tarjan_equals_kosaraju_test() ` | Different SCC algorithms produce same components | ✅ |
8484| 2 | Kruskal MST weight = Prim MST weight | ` mst_kruskal_equals_prim_weight_test() ` | Different MST algorithms produce same total weight | ✅ |
8585| 3 | Bellman-Ford = Dijkstra (non-negative) | ` bellman_ford_equals_dijkstra_test() ` | Algorithms agree on non-negative weighted graphs | ✅ |
8686
8787### Pathfinding Correctness
8888
8989| # | Property | Test Function | Rationale | Status |
90- | ---| ----------| ---------------| -----------| --------|
90+ | --- | ---------- | --------------- | ----------- | -------- |
9191| 4 | Dijkstra path validity | ` dijkstra_path_validity_test() ` | Path starts/ends correctly, edges exist, weight accurate | ✅ |
9292| 5 | No-path detection | ` dijkstra_no_path_confirmed_by_bfs_test() ` | Dijkstra None confirmed by BFS unreachability | ✅ |
9393| 6 | Undirected path symmetry | ` undirected_path_symmetry_test() ` | Path weight A→B equals B→A in undirected graphs | ✅ |
@@ -96,7 +96,7 @@ gleam test
9696### Complex Invariants
9797
9898| # | Property | Test Function | Rationale | Status |
99- | ---| ----------| ---------------| -----------| --------|
99+ | --- | ---------- | --------------- | ----------- | -------- |
100100| 8 | SCC components partition graph | ` scc_partition_test() ` | Components are disjoint and cover all nodes | ✅ |
101101| 9 | MST is spanning tree | ` mst_spanning_tree_test() ` | MST reaches all nodes in connected graph | ✅ |
102102| 10 | Bridge removal disconnects graph | ` bridge_removal_test() ` | Removing bridge increases connected components | ✅ |
@@ -110,14 +110,14 @@ gleam test
110110
111111Two complementary strategies are used:
112112
113- ** 1. Property-Based Testing (PBT)**
113+ #### Property-Based Testing (PBT)
114114
115115- Random graph generation via ` qcheck `
116116- ~ 100 test cases per property
117117- Graph sizes: 0-15 nodes, 0-30 edges
118118- Best for: Structural properties, transformations
119119
120- ** 2. Example-Based Testing**
120+ #### Example-Based Testing
121121
122122- Specific graph configurations
123123- Deterministic, fast execution
@@ -143,11 +143,10 @@ qcheck = ">= 1.0.0 and < 2.0.0"
143143
144144- Test framework: ` gleeunit `
145145- Property library: ` qcheck ` v1.0.4
146- - Test timeout: 120s default
147146- Shrinking: Automatic (qcheck)
148147
149148## References
150149
151- - qcheck documentation: https://hexdocs.pm/qcheck/
152- - QuickCheck paper: https://www.cs.tufts.edu/~nr/cs257/archive/john-hughes/quick.pdf
153- - Property-Based Testing: https://hypothesis.works/articles/what-is-property-based-testing/
150+ - qcheck documentation: < https://hexdocs.pm/qcheck/ >
151+ - QuickCheck paper: < https://www.cs.tufts.edu/~nr/cs257/archive/john-hughes/quick.pdf >
152+ - Property-Based Testing: < https://hypothesis.works/articles/what-is-property-based-testing/ >
0 commit comments