Skip to content

Commit

Permalink
perfect-numbers: Update tests from table-based to macro-based
Browse files Browse the repository at this point in the history
This PR is in response to exercism#392.

Perfect-numbers currently uses table-based testing. For reasons outlined
in exercism#392 (comment)
I believe that table-based testing is not the appropriate way to do things.

This is what macro-based tests might look like. Are they abstruse and
opaque? Yes. However, they at least become individual tests, and I
believe that this is _better than the status quo_.

Squashed commits:
- Conditionally disable count-ignores.sh; disable for perfect-numbers
- Document .meta/ignore-count-ignores
- Update to use inline ignores
  • Loading branch information
coriolinus committed Nov 20, 2017
1 parent b61d2e3 commit e943898
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 30 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ Note that:

- If the test suite is appreciably sped up by running in release mode, and there is reason to be confident that the example implementation does not contain any overflow errors, consider adding a file `.meta/test-in-release-mode`. This should contain brief comments explaining the situation.

- If your exercise implements macro-based testing (see [#392](https://github.com/exercism/rust/issues/392#issuecomment-343865993) and [`perfect-numbers.rs`](https://github.com/exercism/rust/blob/master/exercises/perfect-numbers/tests/perfect-numbers.rs)), you will likely run afoul of a CI check which counts the `#[ignore]` lines and compares the result to the number of `#[test]` lines. To fix this, add a file `.meta/ignore-count-ignores` to disable that check for your exercise.

- `README.md` may be [regenerated](https://github.com/exercism/docs/blob/master/maintaining-a-track/regenerating-exercise-readmes.md) from Exercism data. The generator will use the `description.md` from the exercise directory in the [problem-specifications repository](https://github.com/exercism/problem-specifications/tree/master/exercises), then any hints in `.meta/hints.md`, then the [Rust-specific instructions](https://github.com/exercism/rust/blob/master/config/exercise-readme-insert.md). The `## Source` section comes from the `metadata.yml` in the same directory. Convention is that the description of the source remains text and the link is both name and hyperlink of the markdown link.

- Be sure to add the exercise to an appropriate place in the `config.json` file. The position in the file determines the order exercises are sent. Generate a unique UUID for the exercise. Current difficuly levels in use are 1, 4, 7 and 10.
Expand Down
23 changes: 15 additions & 8 deletions _test/count-ignores.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@
repo=$(cd "$(dirname "$0")/.." && pwd)
exitcode=0

for t in $repo/exercises/*/tests/*.rs; do
tests=$(grep "^\s*\#\[test\]" $t | wc -l | tr -d '[:space:]')
ignores=$(grep "^\s*\#\[ignore\]" $t | wc -l | tr -d '[:space:]')
want_ignores=$(expr $tests - 1)
if [ "$ignores" != "$want_ignores" ]; then
echo "\033[1;31m$t: Has $tests tests and $ignores ignores (should be $want_ignores)\033[0m"
exitcode=1
fi
for e in $repo/exercises/*; do
if [ -f "$e/.meta/ignore-count-ignores" ]; then
continue
fi
if [ -d "$e/tests" ]; then
for t in $e/tests/*.rs; do
tests=$(grep "^\s*\#\[test\]" $t | wc -l | tr -d '[:space:]')
ignores=$(grep "^\s*\#\[ignore\]" $t | wc -l | tr -d '[:space:]')
want_ignores=$(expr $tests - 1)
if [ "$ignores" != "$want_ignores" ]; then
echo "\033[1;31m$t: Has $tests tests and $ignores ignores (should be $want_ignores)\033[0m"
exitcode=1
fi
done
fi
done

exit $exitcode
6 changes: 6 additions & 0 deletions exercises/perfect-numbers/.meta/ignore-count-ignores
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Perfect numbers has tests generated by macro.
This breaks the count-ignores.sh script:

```text
exercises/perfect-numbers/tests/perfect-numbers.rs: Has 2 tests and 11 ignores (should be 1)
```
54 changes: 32 additions & 22 deletions exercises/perfect-numbers/tests/perfect-numbers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,42 @@ extern crate perfect_numbers;

use perfect_numbers::{Classification, classify};

macro_rules! tests {
($property_test_func:ident {
$( $(#[$attr:meta])* $test_name:ident( $( $param:expr ),* ); )+
}) => {
$(
$(#[$attr])*
#[test]
fn $test_name() {
$property_test_func($( $param ),* )
}
)+
}
}

fn test_classification(num: u64, result: Classification) {
assert_eq!(classify(num), Ok(result));
}

#[test]
fn basic() {
assert_eq!(classify(0), Err("Number must be positive"));
}

#[test]
#[ignore]
fn test_all() {
struct TestClassification {
num: u64,
result: perfect_numbers::Classification
}
let test_table: Vec<TestClassification> = vec![
TestClassification { num: 6, result: Classification::Perfect },
TestClassification { num: 28, result: Classification::Perfect },
TestClassification { num: 33550336, result: Classification::Perfect },
TestClassification { num: 12, result: Classification::Abundant },
TestClassification { num: 30, result: Classification::Abundant },
TestClassification { num: 33550335, result: Classification::Abundant },
TestClassification { num: 2, result: Classification::Deficient },
TestClassification { num: 4, result: Classification::Deficient },
TestClassification { num: 32, result: Classification::Deficient },
TestClassification { num: 33550337, result: Classification::Deficient },
TestClassification { num: 1, result: Classification::Deficient },
];
for t in test_table {
assert_eq!(classify(t.num), Ok(t.result));

tests! {
test_classification {
#[ignore] test_1(1, Classification::Deficient);
#[ignore] test_2(2, Classification::Deficient);
#[ignore] test_4(4, Classification::Deficient);
#[ignore] test_6(6, Classification::Perfect);
#[ignore] test_12(12, Classification::Abundant);
#[ignore] test_28(28, Classification::Perfect);
#[ignore] test_30(30, Classification::Abundant);
#[ignore] test_32(32, Classification::Deficient);
#[ignore] test_33550335(33550335, Classification::Abundant);
#[ignore] test_33550336(33550336, Classification::Perfect);
#[ignore] test_33550337(33550337, Classification::Deficient);
}
}

0 comments on commit e943898

Please sign in to comment.