DEV Community

Nicolas DUBIEN
Nicolas DUBIEN

Posted on • Edited on

2 1

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.

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay