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");
}
)
);
});
```

## 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");
}
)
);
});
```

## 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");
}
)
);
});
```

## 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");
}
)
);
});
```

## 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");
}
)
);
});
```

## 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");
}
)
);
});
```

## 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");
}
)
);
});
```

## 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));
}
)
);
});
```

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)