【问题标题】:Testing: Parameter input validation测试:参数输入验证
【发布时间】:2011-03-06 11:48:14
【问题描述】:

在下面的代码中,我想知道是否可以调整进行名称检查的测试。因为一旦我添加了检查 ID 不能为空的代码,我的前 3 个测试就会失败。

最后 3 个进行 id 测试的测试也是如此。我必须使用“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

更新: 我想一种解决方案是为 id 和 name 设置一个 getter 和 setter 方法,然后测试它们。

【问题讨论】:

  • 您忘记提及您使用的是哪个测试库。看起来像Speks
  • 更多 StackOverflow 问题?
  • 是的,我也是这么想的。我是否删除此问题并将其复制粘贴到 SO?
  • 不,不要复制粘贴。点击“举报”并请版主为您移动。
  • 一个建议:假设您希望拒绝非字符串名称,您可能希望将 name? 检查替换为 typeof name is 'string'。同样,也许typeof id is 'number' 而不是number?。或者,如果您想允许非字符串名称或非数字 id,您应该在某些测试用例中使用它们。

标签: javascript coffeescript


【解决方案1】:

在 matyr 的以下评论后编辑:我最初认为这是由于 new 运算符的古怪,因为一些测试使用语法 new Foo().bar。但是,new 在这些情况下的行为与 Pickels 的预期相同。因此,尽管此答案不是所述问题的解决方案,但为了后代的缘故,这里是一个评论:

当你写作时

new A().B

您正在引用新 A 实例的 B 属性。

但是如果你写

new A.B()

(或者只是new A.B——如果new 目标不存在,CoffeeScript 会在它们的末尾隐式添加括号)然后您将创建A.B 的新实例。这变得相当混乱——new A().B() 是什么?——因为new 运算符有自己的特殊优先级规则。因此,我建议使用括号来阐明此类代码,例如

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

曾有discussion here 试图在 CoffeeScript 中让这种行为更直观,但经过积极努力,最终确定“治愈比疾病更糟糕”。

【讨论】:

  • 哇,我居然不知道这个。
  • 是的,这肯定会让我们人类感到困惑,尽管如果您是编译器,这完全有道理——new 之后的所有内容都被评估为单个表达式。 :) 这解决了你原来的问题吗?
  • new Node('foo').name 等于 (new Node('foo')).name,而不是 new (Node('foo').name)。重读#619?
  • 对此很抱歉——我有一种令人讨厌的感觉,认为我的帖子中有错误,但你比我更正了它。正在修改...
【解决方案2】:

让我再试一次:现在,您有三个测试失败。让我们弄清楚如何解决每个故障。

测试 #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 name 而不是if name?,可能会导致'' 的行为与长度> 0 的字符串不同。

测试#3

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

这个测试失败了,因为() -> new Node() 定义了一个函数——一个永远不会运行的函数。我想你的意思是只写new Node()

其他想法

查看Speks 文档,听起来像是使用beforeEach 减少了重复实例声明代码的首选样式。当然,这在您测试构造函数本身时不起作用,但您可能希望在将来的大部分测试中使用它。

这是您的测试套件的重写版本,其中包含所有这些建议并将测试分为三种类型:创建异常的测试、预期正常行为的测试以及对象应该 行为正常,但属于极端情况:

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('')

【讨论】:

  • 这解决了我的问题,谢谢。不过我有一条评论。如果我读到有关 TDD 的内容,他们会说您应该编写尽可能少的代码以使您的测试通过。因此,要进行像 expect( (new Node('foo')).name )toEqual('foo') 这样的测试,您可以硬编码要返回的字符串 'foo'。这就是为什么对“bar”进行测试的原因。我以此为起点:blog.extracheese.org/2009/11/how_i_started_tdd.html
  • 啊,如果您先编写规范,那么是的,我可以看到额外测试的优势。 :)
猜你喜欢
  • 2017-06-27
  • 1970-01-01
  • 2020-06-13
  • 2011-08-03
  • 2022-10-30
  • 1970-01-01
  • 1970-01-01
  • 2015-05-31
  • 2018-12-27
相关资源
最近更新 更多