СУХОЙ ЖАСМИН ВЛОЖЕННЫЙ
Я пытаюсь проверить код представления с помощью жасмина. Мне нужно проверить наличие определенных элементов, когда объект представления находится в различных включающих состояниях, без необходимости повторения большого количества кода в каждом состоянии.
У меня есть класс NodeView, который представляет узел с некоторыми конечными точками, чтобы позволить пользователю подключить этот узел к другим узлам с некоторыми линиями. Каждый узел помещается в столбец (группу), поэтому, если этот узел помещается в первую группу, он не будет отображать левую конечную точку. Если узел находится в последней группе, он не покажет правильную конечную точку. Я могу справиться с этой ситуацией, используя вложенные блоки описания в jasmine:
var node, subject, model;
describe("render", function() {
beforeEach(function() {
model = mockModel();
});
describe("when the node is into first group", function() {
beforeEach(function () {
model.isInFirstGroup.andReturn(true);
model.isInLastGroup.andReturn(false);
node = new NodeView(model);
});
it("has the left endpoint hidden", function() {
expect(node.el.find('.endpoint .left')).toBeHidden();
});
it("has the right endpoint visible", function() {
expect(node.el.find('.endpoint .left')).toBeVisible();
});
});
describe("when the node is into last group", function() {
beforeEach(function () {
model.isInFirstGroup.andReturn(false);
model.isInLastGroup.andReturn(true);
node = new NodeView(model);
});
it("has the left endpoint visible", function() {
expect(node.el.find('.endpoint .left')).toBeVisible();
});
it("has the right endpoint hidden", function() {
expect(node.el.find('.endpoint .left')).toBeHidden();
});
});
Пока все в порядке. Проблемы начинаются, когда у нас есть другие различные состояния, в этом случае это состояние позволяет вводить. это логическое значение, которое указывает, может ли пользователь рисовать линии. Если это логическое значение true, тогда узел должен содержать класс "input" среди других вещей. Вот код (функция рендеринга снова):
describe("when the node is in input state", function() {
beforeEach(function() {
model.input = true;
node = new NodeView(model);
});
it("has the class input", function(){
expect(node.el).toHaveClass('input');
});
});
describe("when the node is not in input state", function() {
beforeEach(function() {
model.input = false;
node = new NodeView(model);
});
it("has not the class input", function(){
expect(node.el).not.toHaveClass('input');
});
});
Хорошо, хорошо, я тестирую сгенерированную html-разметку при построении узла (не вызывая метод render явно), но он выполняет эту работу внутренне. Render вызывается при построении объекта (конструктор вызывает render), поэтому я не вызываю node.render() явно в коде.
Тестирование этих различных состояний потребовало бы, чтобы тест включал все возможные ситуации:
- первая группа - вход
- последняя группа - вход
- первая группа - без ввода
- последняя группа - без ввода
Если я добавлю еще одно логическое состояние, то у меня будет 8 сценариев и так далее. Я попытался немного почистить его, используя общие примеры http://pivotallabs.com/drying-up-jasmine-specs-with-shared-behavior/
sharedExamplesForGroupState = function() {
describe("(shared)", function() {
describe("when the node is into first group", function() {
beforeEach(function () {
model.isInFirstGroup.andReturn(true);
model.isInLastGroup.andReturn(false);
node = new NodeView(model);
});
it("has the left endpoint hidden", function() {
expect(node.el.find('.endpoint .left')).toBeHidden();
});
it("has the right endpoint visible", function() {
expect(node.el.find('.endpoint .left')).toBeVisible();
});
});
describe("when the node is into last group", function() {
beforeEach(function () {
model.isInFirstGroup.andReturn(false);
model.isInLastGroup.andReturn(true);
node = new NodeView(model);
});
it("has the left endpoint visible", function() {
expect(node.el.find('.endpoint .left')).toBeVisible();
});
it("has the right endpoint hidden", function() {
expect(node.el.find('.endpoint .left')).toBeHidden();
});
});
});
});
describe("when the node is in input state", function() {
beforeEach(function() {
model.input = true;
node = new NodeView(model);
});
it("has the class input", function(){
expect(node.el).toHaveClass('input');
});
sharedExamplesForGroupState();
});
describe("when the node is not in input state", function() {
beforeEach(function() {
model.input = false;
node = new NodeView(model);
});
it("has not the class input", function(){
expect(node.el).not.toHaveClass('input');
});
sharedExamplesForGroupState();
});
Вышеуказанные строки не работают должным образом, потому что тесты состояния ввода выполняются без установки состояния ввода, поэтому то, что мы на самом деле тестируем, таково:
- вход и нет входа независимо от группы
- первая и последняя группа без учета входных тестовых случаев, но с атрибутом model.input
Это на самом деле не тестирование всех 4 случаев.
Любые идеи о том, как улучшить это, чтобы избежать экспоненциально повторяющегося кода?
Большое спасибо.
1 ответ
Я думаю, что функция обратного вызова, которую регистрирует beforeEach в ваших последних описывающих блоках, переопределяется вызовом beforeEach при вызове sharedExamplesForGroupState(). Если вы создаете новую область для вызова sharedExamplesForGroupState (например, заключая ее в блок описания), она должна работать:
describe("when the node is in input state", function() {
beforeEach(function() {
model.input = true;
node = new NodeView(model);
});
it("has the class input", function(){
expect(node.el).toHaveClass('input');
});
describe("shared examples for group state", function() {
sharedExamplesForGroupState();
});
});