2

次のコードでは、名前チェックを行うテストを調整してもよいかどうか疑問に思っていました。ID を null にできないことを確認するコードを追加すると、最初の 3 つのテストが失敗するためです。

同じことが、id テストを行う最後の 3 つのテストにも当てはまります。名前の原因として「foo」を使用する必要があります。そうしないと、これらのテストも失敗します。それも大丈夫かどうかわかりませんか?

テストするコード:

class Error

class Node
    constructor: (name, id) ->
        if not name?
            throw new Error('Name cannot be null')

        @name = name

        if not id?
            throw new Error('Id cannot be null')

        @id = id

window.Node = Node

仕様:

node_spec = describe 'Node', () ->

    it 'should have the name foo', () ->
        expect( new Node('foo').name ).toEqual('foo')

    it 'should have the name bar', () ->
        expect( new Node('bar').name ).toEqual('bar')

    it 'should throw an error if the name is null', () ->
        expect( () -> new Node() ).toThrow()

    it 'should have an id of 0', () ->
        expect( new Node('foo', 0).id ).toEqual(0)

    it 'should have an of 1', () ->
        expect( new Node('foo', 1).id ).toEqual(1)

    it 'should throw an error if id is null', () ->
        expect( new Node('foo') ).toThrow()

window.node_spec = node_spec

更新: 解決策の 1 つは、id と name の両方にゲッター メソッドとセッター メソッドを用意し、代わりにそれらをテストすることだと思います。

4

2 に答える 2

3

以下の matyr のコメントの後に編集:newいくつかのテストで構文が使用されているため、これは演算子の奇抜さによるものだと最初は信じていましたnew Foo().bar。しかし、newそのような状況では、ピッケルズが期待したとおりに動作します。したがって、この回答は前述の問題の解決策ではありませんが、後世のためにレビューします。

あなたが書くとき

new A().B

B新しいAインスタンスのプロパティを参照しています。

しかし、あなたが書くなら

new A.B()

(または単にnew A.B—CoffeeScript は、ターゲットの末尾に括弧newがない場合は暗黙的に括弧を追加します) の新しいインスタンスを作成していますA.B。演算子には独自の特別な優先順位規則がnew A().B()あるため、これはかなり混乱します。newしたがって、括弧を使用してそのようなコードを明確にすることをお勧めします。

(new A).B
new (A.B)

ここでは、CoffeeScript でこの動作をより直感的にしようとする試みについて議論がありましたが、精力的な努力の結果、「治療は病気よりも悪い」と判断されました。

于 2011-03-05T19:46:42.667 に答える
1

もう一度試してみましょう: 現在、失敗しているテストが 3 つあります。それぞれの失敗に対処する方法を考えてみましょう。

テスト #1

expect( new Node('foo').name ).toEqual('foo')

idが見つからないため、これはエラーになります。そのエラーのテストを保持します。

expect( new Node('foo') ).toThrow()

そして、テスト行と同じように、テスト #1 を書き直して、正当でエラーのないNodeインスタンスを宣言します。id

expect( new Node('foo', 1).name ).toEqual('foo')

それは何も悪いことではありません。エラーのない動作をテストするたびに、適切にインスタンス化する必要があります。この場合、名前と ID を渡すことを意味します。

テスト #2

expect( new Node('bar').name ).toEqual('bar')

これは基本的にテスト #1 と同じです。実際、ここでは徹底的にテストしすぎていると思います。質問する必要があるのは、次のとおりです。'bar'代わりに名前として渡すと'foo'、異なる動作が生じると信じる理由がありますか? 私は「いいえ」と言うでしょう。

したがって、'bar'テストを完全に削除するか'bar'、 (空の文字列を名前として''許可したい場合) に置き換えorます。?if nameif name?''

テスト #3

expect( () -> new Node() ).toThrow()

() -> new Node()このテストは、関数 (実行されない関数) を定義しているため、失敗しています。代わりに書くつもりだと思いますnew Node()

他の考え

Speksのドキュメントを見ると、beforeEach. もちろん、これはコンストラクター自体をテストしているときには機能しませんが、将来、テストの大部分に使用したくなるかもしれません。

以下は、これらの提案をすべて組み込み、テストを 3 つのタイプに分けて書き直したバージョンのテスト スイートです

node_spec = describe 'Node', () ->

  # exception tests
  it 'should throw an error if there are no arguments', () ->
      expect( new Node() ).toThrow()

  it 'should throw an error if there is only one argument', () ->
      expect( new Node('foo') ).toThrow()

  # normal tests
  node = new Node('foo', 1)

  it 'should have an id of 1', () ->
      expect( node.id ).toEqual(1)

  it 'should have the name foo', () ->
      expect( node.name ).toEqual('foo')

  # slightly unusual case of id = 0, name = '' (convertible to false)
  node = new Node('', 0)

  it 'should have an id of 0', () ->
      expect( node.id ).toEqual(0)

  it 'should have an empty string as its name', () ->
      expect( node.name ).toEqual('')
于 2011-03-06T03:48:14.750 に答える