3

ジャスミンを使用していくつかのビュー コードをテストしようとしています。ビュー オブジェクトがさまざまな包括的状態にあるときに、特定の要素の存在をテストする必要があります。状態ごとに多くのコードを繰り返す必要はありません。

ユーザーがこのノードをいくつかの線で他のノードに接続できるようにするために、いくつかのエンドポイントを持つノードを表すクラス NodeView を取得しました。各ノードは列 (グループ) に配置されるため、このノードが最初のグループに配置されると、左端点は表示されません。ノードが最後のグループにある場合、正しいエンドポイントは表示されません。ジャスミンでネストされた記述ブロックを使用して、この状況を管理できます。

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 の場合、ノードには「入力」クラスが含まれている必要があります。コードは次のとおりです(レンダリング関数を再度):

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 つのケースすべてをテストしているわけではありません。

指数関数的に繰り返されるコードを回避するためにこれを改善する方法についてのアイデアはありますか?

どうもありがとう。

4

1 に答える 1

2

最新の記述ブロックの beforeEach が登録しているコールバック関数は、sharedExamplesForGroupState() 呼び出しでの beforeEach 呼び出しによってオーバーライドされていると思います。sharedExamplesForGroupState 呼び出しの新しいスコープを作成すると (describe ブロックに囲むなど)、動作するはずです。

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();
  });
});
于 2014-01-21T09:07:48.283 に答える