DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Nicolas DUBIEN
Nicolas DUBIEN

Posted on • Updated on

Advent of PBT 2021 - Day 11

Advent of PBT 2021 β€” Learn how to use property based testing and fast-check through examples

Our algorithm today is: hanoiTower.
It comes with the following documentation and prototype:

/**
 * In hanoi tower, we consider disks having sizes ranging from 1 to
 * towerHeight (included). We want to move this tower from a given
 * start position to an end position.
 *
 * But to do so we have several rules to follow:
 * - disk can only be moved on top of another one with larger size
 *   (or position empty)
 * - one disk at a time
 * - cannot move disks outside of the tower
 *
 * For instance the hanoi game with towerHeight=3 and startPosition=0
 * at start time is:
 *
 *    X   (1)    |          |
 *   XXX  (2)    |          |
 *  XXXXX (3)    |          |
 *  --+--      --+--      --+--
 *
 * @param towerHeight - The height of the hanoi tower
 *                      (between 0 and 10)
 * @param startPosition - The position of the hanoi tower at start
 *                        time (one of 0, 1 or 2)
 * @param endPosition - The position of the hanoi tower at the end
 * @param move - Move function called each time the function wants
 *               to move the disk on top of "from" to the top of "to"
 */
declare function hanoiTower(
  towerHeight: number,
  startPosition: number,
  endPosition: number,
  move: (from: number, to: number) => void
): void;
Enter fullscreen mode Exit fullscreen mode

We already wrote some examples based tests for it:

it("should be able to move a tower of size 3 from 0 to 2", () => {
  const move = jest.fn();
  hanoiTower(3, 0, 2, move);
  expect(move.mock.calls).toEqual([
    // state: (1/2/3) / () / ()
    [0, 2],
    // state: (2/3) / () / (1)
    [0, 1],
    // state: (3) / (2) / (1)
    [2, 1],
    // state: (3) / (1/2) / ()
    [0, 2],
    // state: () / (1/2) / (3)
    [1, 0],
    // state: (1) / (2) / (3)
    [1, 2],
    // state: (1) / () / (2/3)
    [0, 2]
    // state: () / () / (1/2/3)
  ]);
});

it("should be able to move a tower of size 3 from 2 to 1", () => {
  const move = jest.fn();
  hanoiTower(3, 2, 1, move);
  expect(move.mock.calls).toEqual([
    // state: () / () / (1/2/3)
    [2, 1],
    // state: () / (1) / (2/3)
    [2, 0],
    // state: (2) / (1) / (3)
    [1, 0],
    // state: (1/2) / () / (3)
    [2, 1],
    // state: (1/2) / (3) / ()
    [0, 2],
    // state: (2) / (3) / (1)
    [0, 1],
    // state: () / (2/3) / (1)
    [2, 1]
    // state: () / (1/2/3) / ()
  ]);
});
Enter fullscreen mode Exit fullscreen mode

How would you cover it with Property Based Tests?

In order to ease your task we provide you with an already setup CodeSandbox, with examples based tests already written and a possible implementation of the algorithm: https://codesandbox.io/s/advent-of-pbt-day-11-dgrk3?file=/src/index.spec.ts&previewwindow=tests

You wanna see the solution? Here is the set of properties I came with to cover today's algorithm: https://dev.to/dubzzz/advent-of-pbt-2021-day-11-solution-1og1


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)

Let's Get Hacking

Join the DEV x Linode Hackathon 2022 and use your ingenuity and creativity to build using Linode.

β†’ Join the Hackathon <-