DEV Community

Nicolas DUBIEN
Nicolas DUBIEN

Posted on • Updated on

Advent of PBT 2021 - Day 3 - Solution

Our algorithm was: fizzbuzz.
Go to the subject itself for more details

CodeSandbox with a possible set of properties you may have come with: https://codesandbox.io/s/advent-of-pbt-day-3-solution-q7x2v?file=/src/index.spec.ts&previewwindow=tests


Before we start with the properties, there is one main pitfall with fizzbuzz: it is easy to rewrite the implementation in the test itself. So if your tests are using modulo, you are probably rewriting the implementation of fizzbuzz directly inside your tests.

Except that trap, properties are quite straight-word for fizzbuzz, so we will just show the code.


Property 1: should print Fizz whenever divisible by 3

Instead of checking if the number is divisible by 3, we create one divisible by 3.

it("should print Fizz whenever divisible by 3", () => {
  fc.assert(
    fc.property(
      fc.nat().map((n) => n * 3),
      (n) => {
        expect(fizzbuzz(n)).toContain("Fizz");
      }
    )
  );
});
Enter fullscreen mode Exit fullscreen mode

Property 2: should not print Fizz when not divisible by 3

Instead of checking if the number is not divisible by 3, we create one not divisible by 3.

it("should not print Fizz when not divisible by 3", () => {
  fc.assert(
    fc.property(
      fc.oneof(
        fc.nat().map((n) => n * 3 + 1),
        fc.nat().map((n) => n * 3 + 2)
      ),
      (n) => {
        expect(fizzbuzz(n)).not.toContain("Fizz");
      }
    )
  );
});
Enter fullscreen mode Exit fullscreen mode

Property 3: should only print Fizz when divisible by 3 but not by 5

it("should only print Fizz when divisible by 3 but not by 5", () => {
  fc.assert(
    fc.property(
      fc.oneof(
        fc
          .nat()
          .map((n) => n * 5 + 1)
          .map((n) => n * 3),
        fc
          .nat()
          .map((n) => n * 5 + 2)
          .map((n) => n * 3),
        fc
          .nat()
          .map((n) => n * 5 + 3)
          .map((n) => n * 3),
        fc
          .nat()
          .map((n) => n * 5 + 4)
          .map((n) => n * 3)
      ),
      (n) => {
        expect(fizzbuzz(n)).toBe("Fizz");
      }
    )
  );
});
Enter fullscreen mode Exit fullscreen mode

Property 4: should print Buzz whenever divisible by 5

it("should print Buzz whenever divisible by 5", () => {
  fc.assert(
    fc.property(
      fc.nat().map((n) => n * 5),
      (n) => {
        expect(fizzbuzz(n)).toContain("Buzz");
      }
    )
  );
});
Enter fullscreen mode Exit fullscreen mode

Property 5: should not print Buzz when not divisible by 5

it("should not print Buzz when not divisible by 5", () => {
  fc.assert(
    fc.property(
      fc.oneof(
        fc.nat().map((n) => n * 5 + 1),
        fc.nat().map((n) => n * 5 + 2),
        fc.nat().map((n) => n * 5 + 3),
        fc.nat().map((n) => n * 5 + 4)
      ),
      (n) => {
        expect(fizzbuzz(n)).not.toContain("Buzz");
      }
    )
  );
});
Enter fullscreen mode Exit fullscreen mode

Property 6: should only print Buzz when divisible by 5 but not by 3

it("should only print Buzz when divisible by 5 but not by 3", () => {
  fc.assert(
    fc.property(
      fc.oneof(
        fc
          .nat()
          .map((n) => n * 3 + 1)
          .map((n) => n * 5),
        fc
          .nat()
          .map((n) => n * 3 + 2)
          .map((n) => n * 5)
      ),
      (n) => {
        expect(fizzbuzz(n)).toBe("Buzz");
      }
    )
  );
});
Enter fullscreen mode Exit fullscreen mode

Property 7: should print Fizz Buzz whenever divisible by 3 and 5

it("should print Fizz Buzz whenever divisible by 3 and 5", () => {
  fc.assert(
    fc.property(
      fc
        .nat()
        .map((n) => n * 3)
        .map((n) => n * 5),
      (n) => {
        expect(fizzbuzz(n)).toBe("Fizz Buzz");
      }
    )
  );
});
Enter fullscreen mode Exit fullscreen mode

Property 8: should print the value itself when not divisible by 3 and not divisible by 5

it("should print the value itself when not divisible by 3 and not divisible by 5", () => {
  fc.assert(
    fc.property(
      fc.oneof(
        fc.nat().map((n) => n * 15 + 1),
        fc.nat().map((n) => n * 15 + 2),
        fc.nat().map((n) => n * 15 + 4), // +3 would be divisible by 3
        fc.nat().map((n) => n * 15 + 7), // +5 would be divisible by 5, +6 would be divisible by 3
        fc.nat().map((n) => n * 15 + 8), // +9 would be divisible by 3, +10 would be divisible by 5
        fc.nat().map((n) => n * 15 + 11),
        fc.nat().map((n) => n * 15 + 13), // +12 would be divisible by 3
        fc.nat().map((n) => n * 15 + 14)
      ),
      (n) => {
        expect(fizzbuzz(n)).toBe(String(n));
      }
    )
  );
});
Enter fullscreen mode Exit fullscreen mode

Back to "Advent of PBT 2021" to see topics covered during the other days and their solutions.

More about this serie on @ndubien or with the hashtag #AdventOfPBT.

Top comments (0)