Skip to content

Restructure tests: split test and source code#27

Merged
GiggleLiu merged 3 commits intomainfrom
restructure-tests
Feb 8, 2026
Merged

Restructure tests: split test and source code#27
GiggleLiu merged 3 commits intomainfrom
restructure-tests

Conversation

@isPANN
Copy link
Collaborator

@isPANN isPANN commented Feb 7, 2026

Summary

  • Extract inline #[cfg(test)] mod tests blocks from 73 src/ files into src/unit_tests/ using #[path] attributes
  • Consolidate 6 integration test binaries into 1 (tests/main.rs)
  • Move internal tests (property, reduction graph, trait consistency, unitdiskmapping algorithms) from tests/ to src/unit_tests/, organized by function
  • Keep only user-facing tests in tests/: problem creation, solving, reductions, I/O, end-to-end workflows (and this may need to design carefully in the future)

Test plan

  • make test — all 1582 tests pass, 0 failures
  • make clippy — no warnings
  • No tests deleted — all test code preserved or duplicated

Closes #23

🤖 Generated with Claude Code

…te integration tests

- Extract #[cfg(test)] mod tests blocks from 73 src/ files into src/tests_unit/ using #[path]
- Consolidate 6 integration test binaries into 1 (tests/main.rs)
- Move internal tests (property, reduction graph, trait consistency, unitdiskmapping algorithms) from tests/ to src/tests_unit/
- Keep only user-facing tests in tests/: integration.rs and reductions.rs
- All 1582 tests preserved, 0 failures, clippy clean

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@codecov
Copy link

codecov bot commented Feb 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.21%. Comparing base (a884852) to head (9ed09d1).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #27      +/-   ##
==========================================
- Coverage   97.21%   97.21%   -0.01%     
==========================================
  Files          76      160      +84     
  Lines       21391    25163    +3772     
==========================================
+ Hits        20796    24463    +3667     
- Misses        595      700     +105     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

- Rename tests_unit → unit_tests for clearer distinction from src/testing/
- Fix test_brute_force_satisfiable: use valid_only(false) so the loop body
  actually executes on the UNSAT instance, covering the 2 missing lines

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@GiggleLiu
Copy link
Contributor

Since AI sometimes generates too many trivial tests, and pollute the source code - finally it either cannot read the whole file or cost too many tokens. I think it is an important refactoring towards scalability. Thank you!

@GiggleLiu GiggleLiu requested a review from Copilot February 8, 2026 00:25
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Restructures the Rust test suite by moving inline unit tests out of src/ into src/unit_tests/ (referenced via #[path]), and consolidates integration tests to keep tests/ focused on user-facing behavior.

Changes:

  • Extracted many inline #[cfg(test)] mod tests blocks into src/unit_tests/ and rewired them via #[path].
  • Added/updated unit-test modules under src/unit_tests/ for models, topology, rules, config, IO, etc.
  • Updated internal docs to codify the new test organization pattern.

Reviewed changes

Copilot reviewed 98 out of 169 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/unit_tests/models/specialized/factoring.rs New extracted unit tests for Factoring.
src/unit_tests/models/specialized/bmf.rs New extracted unit tests for BMF utilities and problem behavior.
src/unit_tests/models/specialized/biclique_cover.rs New extracted unit tests for BicliqueCover.
src/unit_tests/models/set/set_covering.rs New extracted unit tests for SetCovering.
src/unit_tests/models/satisfiability/ksat.rs New extracted unit tests for KSatisfiability.
src/unit_tests/models/optimization/spin_glass.rs New extracted unit tests for SpinGlass.
src/unit_tests/models/optimization/qubo.rs New extracted unit tests for QUBO.
src/unit_tests/models/graph/vertex_covering.rs Switched to use super::* pattern and expanded tests via extracted module.
src/unit_tests/models/graph/kcoloring.rs Switched to use super::* pattern and added extracted tests.
src/unit_tests/models/graph/independent_set.rs Switched to use super::* pattern and added extracted tests.
src/unit_tests/io.rs New extracted unit tests for IO/serialization helpers.
src/unit_tests/graph_types.rs New extracted unit tests for graph subtype registration.
src/unit_tests/graph_models.rs Updated imports to crate::... to work as in-crate unit tests.
src/unit_tests/config.rs New extracted unit tests for ConfigIterator and config conversions.
src/types.rs Replaced inline tests with #[path = "unit_tests/types.rs"] mod tests;.
src/truth_table.rs Replaced inline tests with #[path = "unit_tests/truth_table.rs"] mod tests;.
src/topology/unit_disk_graph.rs Replaced inline tests with #[path = "../unit_tests/topology/unit_disk_graph.rs"] mod tests;.
src/topology/small_graphs.rs Replaced inline tests with #[path = "../unit_tests/topology/small_graphs.rs"] mod tests;.
src/topology/hypergraph.rs Replaced inline tests with #[path = "../unit_tests/topology/hypergraph.rs"] mod tests;.
src/topology/graph.rs Replaced inline tests with #[path = "../unit_tests/topology/graph.rs"] mod tests;.
src/testing/mod.rs Replaced inline tests with #[path = "../unit_tests/testing/mod.rs"] mod tests;.
src/testing/macros.rs Replaced inline tests with #[path = "../unit_tests/testing/macros.rs"] mod tests;.
src/rules/vertexcovering_setcovering.rs Replaced inline tests with #[path = "../unit_tests/rules/vertexcovering_setcovering.rs"] mod tests;.
src/rules/vertexcovering_independentset.rs Replaced inline tests with #[path = "../unit_tests/rules/vertexcovering_independentset.rs"] mod tests;.
src/rules/unitdiskmapping/weighted.rs Replaced inline tests with #[path = "../../unit_tests/rules/unitdiskmapping/weighted.rs"] mod tests;.
src/rules/unitdiskmapping/triangular/mod.rs Replaced inline tests with #[path = "../../../unit_tests/rules/unitdiskmapping/triangular/mod.rs"] mod tests;.
src/rules/unitdiskmapping/triangular/mapping.rs Replaced inline tests with #[path = "../../../unit_tests/rules/unitdiskmapping/triangular/mapping.rs"] mod tests;.
src/rules/unitdiskmapping/pathdecomposition.rs Replaced inline tests with #[path = "../../unit_tests/rules/unitdiskmapping/pathdecomposition.rs"] mod tests;.
src/rules/unitdiskmapping/ksg/mapping.rs Replaced inline tests with #[path = "../../../unit_tests/rules/unitdiskmapping/ksg/mapping.rs"] mod tests;.
src/rules/unitdiskmapping/ksg/gadgets_weighted.rs Replaced inline tests with #[path = "../../../unit_tests/rules/unitdiskmapping/ksg/gadgets_weighted.rs"] mod tests;.
src/rules/unitdiskmapping/grid.rs Replaced inline tests with #[path = "../../unit_tests/rules/unitdiskmapping/grid.rs"] mod tests;.
src/rules/unitdiskmapping/alpha_tensor.rs Replaced inline tests with #[path = "../../unit_tests/rules/unitdiskmapping/alpha_tensor.rs"] mod tests;.
src/rules/traits.rs Replaced inline tests with #[path = "../unit_tests/rules/traits.rs"] mod tests;.
src/rules/spinglass_qubo.rs Replaced inline tests with #[path = "../unit_tests/rules/spinglass_qubo.rs"] mod tests;.
src/rules/spinglass_maxcut.rs Replaced inline tests with #[path = "../unit_tests/rules/spinglass_maxcut.rs"] mod tests;.
src/rules/setpacking_ilp.rs Replaced inline tests with #[path = "../unit_tests/rules/setpacking_ilp.rs"] mod tests;.
src/rules/registry.rs Replaced inline tests with #[path = "../unit_tests/rules/registry.rs"] mod tests;.
src/rules/matching_setpacking.rs Replaced inline tests with #[path = "../unit_tests/rules/matching_setpacking.rs"] mod tests;.
src/rules/independentset_setpacking.rs Replaced inline tests with #[path = "../unit_tests/rules/independentset_setpacking.rs"] mod tests;.
src/rules/cost.rs Replaced inline tests with #[path = "../unit_tests/rules/cost.rs"] mod tests;.
src/registry/info.rs Replaced inline tests with #[path = "../unit_tests/registry/info.rs"] mod tests;.
src/registry/category.rs Replaced inline tests with #[path = "../unit_tests/registry/category.rs"] mod tests;.
src/polynomial.rs Replaced inline tests with #[path = "unit_tests/polynomial.rs"] mod tests;.
src/models/specialized/paintshop.rs Replaced inline tests with #[path = "../../unit_tests/models/specialized/paintshop.rs"] mod tests;.
src/models/specialized/factoring.rs Replaced inline tests with #[path = "../../unit_tests/models/specialized/factoring.rs"] mod tests;.
src/models/specialized/bmf.rs Replaced inline tests with #[path = "../../unit_tests/models/specialized/bmf.rs"] mod tests;.
src/models/specialized/biclique_cover.rs Replaced inline tests with #[path = "../../unit_tests/models/specialized/biclique_cover.rs"] mod tests;.
src/models/set/set_packing.rs Replaced inline tests with #[path = "../../unit_tests/models/set/set_packing.rs"] mod tests;.
src/models/set/set_covering.rs Replaced inline tests with #[path = "../../unit_tests/models/set/set_covering.rs"] mod tests;.
src/models/satisfiability/ksat.rs Replaced inline tests with #[path = "../../unit_tests/models/satisfiability/ksat.rs"] mod tests;.
src/models/optimization/spin_glass.rs Replaced inline tests with #[path = "../../unit_tests/models/optimization/spin_glass.rs"] mod tests;.
src/models/optimization/qubo.rs Replaced inline tests with #[path = "../../unit_tests/models/optimization/qubo.rs"] mod tests;.
src/models/graph/max_cut.rs Replaced inline tests with #[path = "../../unit_tests/models/graph/max_cut.rs"] mod tests;.
src/models/graph/kcoloring.rs Replaced inline tests with #[path = "../../unit_tests/models/graph/kcoloring.rs"] mod tests;.
src/lib.rs Registers extracted internal unit-test modules under #[cfg(test)].
src/io.rs Replaced inline tests with #[path = "unit_tests/io.rs"] mod tests;.
src/graph_types.rs Replaced inline tests with #[path = "unit_tests/graph_types.rs"] mod tests;.
src/config.rs Replaced inline tests with #[path = "unit_tests/config.rs"] mod tests;.
.claude/rules/testing.md Documents new test file organization and discourages inline mod tests.
.claude/CLAUDE.md Updates project layout notes to include src/unit_tests/ and consolidated integration tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 36 to 47
let path = "/tmp/test_problem.json";

// Write
write_problem(&problem, path, FileFormat::Json).unwrap();

// Read back
let restored: IndependentSet<SimpleGraph, i32> = read_problem(path, FileFormat::Json).unwrap();
assert_eq!(restored.num_vertices(), 4);
assert_eq!(restored.num_edges(), 3);

// Cleanup
fs::remove_file(path).ok();
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests write to hardcoded /tmp/... paths, which is not portable (e.g., Windows) and can fail under restricted CI environments. Prefer using std::env::temp_dir() with a unique filename (e.g., timestamp/random) or a tempdir helper so paths are cross-platform and collision-free.

Copilot uses AI. Check for mistakes.

#[test]
fn test_read_write_file() {
let path = "/tmp/test_io.txt";
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests write to hardcoded /tmp/... paths, which is not portable (e.g., Windows) and can fail under restricted CI environments. Prefer using std::env::temp_dir() with a unique filename (e.g., timestamp/random) or a tempdir helper so paths are cross-platform and collision-free.

Copilot uses AI. Check for mistakes.
#[test]
fn test_config_iterator_empty() {
let iter = ConfigIterator::new(0, 2);
assert_eq!(iter.total(), 1);
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test asserts iter.total() == 1 but then expects iter.collect() to produce 0 configurations. Those expectations are inconsistent: if total configurations is 1, collecting should typically yield one empty configuration (vec![]). Either adjust the expectation to configs.len() == 1 (and configs[0] == vec![]), or if the iterator is intentionally empty for num_variables == 0, then total() should likely be 0 to match iteration behavior.

Suggested change
assert_eq!(iter.total(), 1);
assert_eq!(iter.total(), 0);

Copilot uses AI. Check for mistakes.
let solutions = solver.find_best(&problem);
let factor_pairs: Vec<_> = solutions.iter().map(|s| problem.read_factors(s)).collect();

// Should find (1,7) and (7,1)
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says the solver should find both (1, 7) and (7, 1), but the assertion only requires one of them. If both are expected, assert both with &&, or update the comment to match the intended guarantee.

Suggested change
// Should find (1,7) and (7,1)
// Should find at least one of (1,7) or (7,1)

Copilot uses AI. Check for mistakes.
@GiggleLiu
Copy link
Contributor

[fix]

…accurate comment

- Replace hardcoded /tmp/ paths in IO tests with std::env::temp_dir() + unique timestamps
- Fix ConfigIterator::total() to return 0 when num_variables == 0, matching iteration behavior
- Fix factoring test comment to accurately describe the assertion (at least one, not both)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link

github-actions bot commented Feb 8, 2026

Fixed all review comments

  1. Portable temp paths (src/unit_tests/io.rs): Replaced hardcoded /tmp/ paths with std::env::temp_dir() + nanosecond timestamps for cross-platform compatibility and collision-free paths.

  2. ConfigIterator consistency (src/config.rs, src/unit_tests/config.rs): Fixed ConfigIterator::total() to return 0 when num_variables == 0, matching the actual iteration behavior (previously returned 1 via 2^0 but produced 0 items).

  3. Factoring test comment (src/unit_tests/models/specialized/factoring.rs): Updated comment from "Should find (1,7) and (7,1)" to "Should find at least one of (1,7) or (7,1)" to accurately reflect the || assertion.

All CI checks were passing before these changes; fixes are limited to the review feedback.

Copy link
Contributor

@GiggleLiu GiggleLiu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job!

@GiggleLiu GiggleLiu merged commit e22297d into main Feb 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Split test and source code

2 participants