Меню

Введение в Test Driven Development в JS

26.06.2018 - java script, NodeJS, ЯП

Test Driven Development

TDD — это процес написания юнит тестов, до написания самого кода.
При TDD мы следуем слудующему слогану Red, Green and Refactor.

Сначала пишутся простые юнит тесты чтобы знать базовую имплементацию. Мы запускаем их и конечно они будут «провалены» (красный). Затем мы имплементируем функцию и «сдаем» тысты (это зеленая часть). Когда наш код проходит все тесты — самое время для рефакторинга. После рефакторинга убеждаемся, что код всё еще работает и все тесты проходят.

Одно из главные преимуществ TDD это написание чистого самодокументируемого кода. При этом при написании тестов мы как бы делаем себе шаблон, что предполагаемый код должен делать. Можно сказать требования, что мы требуем от нашего кода.

Мы реализуем алгоритмы обхода бинарного дерева.

Начнем наше приключение с имплементированя ноды дерева в файле binary-tree-node.js. Далее в файле binary-tree-ops.js. Здесь будет класс где мы реализуем имплементацию алгоритма обхода дерева. Для начала мы не будет имплементировать методы, мы просто опишем интерфейс. Есть небольшое замечание, которое облегчает жизнь при TDD — желательно явно выкинуть ошибку в неимплементированных методах.

//binary-tree-node.js
class BinaryTreeNode {
    constructor(value, left, right) {
        this.value = value;
        this.left = left;
        this.right = right;
    }
}

module.exports = {
    BinaryTreeNode
};

//binary-tree-ops.js
const { BinaryTreeNode } = require('./binary-tree-node');

class BinaryTreeOps {
    static inOrder(root) {
        throw new Error("Not implemented");
    }

    static preOrder(root) {
        throw new Error("Not implemented");
    }

    static postOrder(root) {
        throw new Error("Not implemented");
    }
}

module.exports = {
    BinaryTreeOps
};

Теперь создаем с помощью

jasmine init

директорию spec, где создаем файл binary-tree-node.spec.js. В нём мы импортируем наши классы.
Теперь мы готовы описать наш BinaryTreeOps класс. Но прежде чем начнем писать, давайте познакомимся с новой функций jasmine — beforeEach. Это функция принимает один единственный аргумент — это колбэк, который будет выполнен каждый раз перед каждым юнит тестом. В ней мы построим наше дерево. Далее в тестах мы описываем, чего мы ждем от наших методов обхода. Здесь мы увидим новый метод toContain. Хорошей практикой считается сравнивать числа методом toEqual, а строки методом toContain.

const {
    BinaryTreeNode
} = require('../app/binary-tree-node');
const {
    BinaryTreeOps
} = require('../app/binary-tree-ops');

describe("BinaryTreeOps", () => {
    let testTree;

    beforeEach(() => {
        testTree = new BinaryTreeNode(4,
            new BinaryTreeNode(6,
                new BinaryTreeNode(2),
                new BinaryTreeNode(1)),
            new BinaryTreeNode(3));
    });

    it("should print the tree's values using in-order traversal", () => {
        let results = BinaryTreeOps.inOrder(testTree);
        expect(results).toContain("2 6 1 4 3");
    });

    it("should print the tree's values usig pre-order traversal", () => {
        let results = BinaryTreeOps.preOrder(testTree);
        expect(results).toContain("4 6 2 1 3");
    });

    it("should print the tree's values usig post-order traversal", () => {
        let results = BinaryTreeOps.postOrder(testTree);
        expect(results).toContain("2 1 6 3 4");
    });
});

В общем — это красная часть слогана Red, Green and Refactor.

Теперь перейдем в binary-tree-ops и начнем имплементировать методы. Начнем с метода inOrder.

//binary-tree-ops.js
const { BinaryTreeNode } = require('./binary-tree-node');

class BinaryTreeOps {
    static inOrder(root) {
        let results = "";
        traverse(root);
        return results;

        function traverse(root) {
            if (!root) return;
            traverse(root.left);
            results += `${root.value} `;
            traverse(root.right);
        }
    }

    static preOrder(root) {
        let results = "";
        traverse(root);
        return results;

        function traverse(root) {
            if (!root) return;

            results += `${root.value} `;
            traverse(root.left);
            traverse(root.right);
        }
    }

    static postOrder(root) {
        let result = "";
        traverse(root);
        return results;

        function traverse(root) {
            if (!root) return;

            traverse(root.left);
            traverse(root.right);
            results += `${root.value} `;
        }
    }
}

module.exports = {
    BinaryTreeOps
};

Теперь мы получили 3 зеленые точки. Наши тесты пройдены. Это второй этап «Red, Green and Refactor» пройден.

Наш код получился и так чистым, поэтому отрефакторить можно только названия внутренних функций.

Метки: , , ,

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *