Правильное тестирование Javascript?

Всем привет! Хотел узнать подробнее про тестирование в Javascript. Использую mocha + chai. Запускаю через gulp. И хотелось бы разобраться поподробнее с типами тестов:
Предполагают ли юнит - тесты зависимость от других классов. То есть мы импортим в тест класс, который импортит в себя другие классы? Возможно ли работать с DOM в импортируемом классе? Это будет считаться юнит - тестом? Что тогда включает в себя интеграционный тест? Помогите, пожалуйста, разобраться с вопросом. Всем заранее спасибо!
  • Вопрос задан
  • 1761 просмотр
Пригласить эксперта
Ответы на вопрос 3
k12th
@k12th
console.log(`You're pulling my leg, right?`);
То есть мы импортим в тест класс, который импортит в себя другие классы?

Надо понимать, что класс не импортирует классы, импорт/экспорт — это модули. Класс может создавать инстансы других классов или принимать инстансы как параметр конструктора, это нормально — во втором случае вы просто пишете mock: заглушку, которая предсказуемо имитирует нужное поведение. Но если вы из модуля экспортируете инстанс класса, то будут проблемы с тестированием. Например, вот так плохо:
// A.js
class A {}
export const a = new A();

// B.js
import { a } from './A';
export class B {
    constructor() {
        this.a = a;
    }

    doStuff() {}
};

Так как класс B неявно зависит от A, то нельзя написать заглушку для A, и тесты для B будут тестировать поведение A.

Вот так лучше:
// A.js
export class A {};

// B.js
export class B {
    constructor(a) {
        this.a = a;
    }

    doStuff() {}
};

// index.js
import { A } from './A';
import { B } from './B';

const a = new A();
const b = new B(a);
b.doStuff();


Возможно ли работать с DOM в импортируемом классе?

Если пускалка тестов это поддерживает. Для mocha, ЕМНИП, надо прикручивать karma.

Это будет считаться юнит-тестом?

Unit-test по определению тестирует какую-то функциональную единицу — класс, модуль, функцию, метод.
Ответ написан
Комментировать
@xfg
В случае если объект внутри себя инстанциирует другой объект, тогда такой объект должен рассматриваться как единый юнит.

import LineItem from './LineItem';

class Order {
  constructor(lineItems = []) {
    this.lineItems = lineItems;
  }
  addLineItem(name, cost, quantity) {
    this.lineItems.push(new LineItem(name, cost, quantity));
  }
}


В этом случае писать юнит-тест необходимо на класс Order. Необходимости в тестировании класса LineItem нет, так как он является составной частью класса Order. Такие классы носят название - Агрегат. Когда автосалон вас приглашает на тест-драйв автомобиля, то это предполагает тестирование Агрегата в целом, то есть Автомобиля. Тестировать отдельно составные его части такие как колеса/двигатель мы не будем.

В случае если объект принимает другой объект из вне, тогда такие объекты должны рассматриваться как отдельные юниты.

class Route {...}
class Ship {
  addRoute(route) {
   if (!(route instanceof Route)) {
     throw new Error('route must be instance of Route');
   }
    this.route = route;
  }
  ...
}


В этом случае необходимо писать отдельные юнит-тесты на Route и на Ship. Чтобы написать юнит-тест на класс Ship его необходимо изолировать от класса Route с помощью мок-объекта.

Интеграционный тест подразумевает, что вы не будете подменять Route на мок-объект, чтобы протестировать класс Ship. Вместо это необходимо передать настоящую реализацию класса Route. В таком случае мы протестируем взаимодействие между двумя юнитами Ship и Route.
Ответ написан
lxsmkv
@lxsmkv
Test automation engineer
--
Как перестать беспокоиться и начать писать тесты

Задача тестов отвечать для Вас на вопросы. Совершенно неважно к какой вымышленной категории Вы эти тесты отнесете.
Важно чтобы при проектировании теста Вы учитывали, что тест доказывает и чего он не доказывает либо не полностью доказывает. Какую информациою он Вам дает и какую не дает. На что он указывает и на что не указывает. У меня масса таких тестов про которые можно сказать "это не 100% гарантия, но лучше чем ничего".
Чем меньше Вы будете беспокоиться о том, к какому типу относятся Ваши тесты, тем быстрее Вы начнете думать о том, а что же я хочу проверить и как я могу это проверить. И просто будете это проверять.

Я читал достаточно разных определений, и скажу что нет единого мнения о том, что как называть. Но есть и хорошая новость - названия не помогут Вам сделать хороший тест. Помогут только правильные вопросы к системе: "в чем я хочу убедиться" и "как я могу в этом убедиться". И поскольку убедиться во всем досконально нехватит никаких ресурсов, Вы начнете искать для себя приемлемые компромиссы, между информационной ценностью тестов и скоростью/легкостью их написания и поддержки.

Чтобы Вы лучше поняли бессмысленность всех этих определений:
Лакмусовая бумажка тоже тест - это интеграционный тест или юнит тест, или это приемочный тест? Где границы системы? Он просто говорит Вам: "Да, уровень кислотности не выше чем". А вопрос к этому ответу соответственно: "Не превышает ли уровень кислотности значение х?". Вам важна информация ("что я хочу знать") и способ получить эту информацию - лакмусовая бумажка.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы