测试:参数输入验证
在下面的代码中,我想知道是否可以调整进行名称检查的测试。因为一旦我添加了检查 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 方法,然后测试它们。
In the following code I was wondering if it's okay to adjust the tests that do the name checking. Because once I add the code that checks that the ID cannot be null my first 3 tests fail.
The same goes for the last 3 tests that do the id testing. I have to use 'foo' as a name cause otherwise those tests will fail too. Not sure if that's okay either?
Code to be tested:
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
The spec:
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
Update:
I guess one solution is to have a getter and setter methods for both id and name and test those instead.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在下面的 matyr 评论后进行编辑:我最初认为这是由于
new
运算符的奇怪之处,因为一些测试使用语法new Foo ().bar
。然而,在这些情况下,new
的行为正如 Pickels 所预期的那样。因此,尽管这个答案不是上述问题的解决方案,但为了后代的缘故,这里有一个回顾:当您编写时,
您正在引用新
的
B
属性一个实例。但是,如果您编写
(或者只是
new AB
- 如果new
目标不存在,CoffeeScript 会在其末尾隐式添加括号),那么您将创建一个新的实例AB
。这变得非常令人困惑——什么是 new A().B()?——因为 new 运算符有自己特殊的优先级规则。因此,我建议使用括号来澄清此类代码,例如这里有讨论关于试图在 CoffeeScript 中使这种行为更加直观,但经过一番努力后,确定“治疗方法比疾病更糟糕”。
Edited after matyr's comment below: I'd initially believed that this was due to the quirkiness of the
new
operator, since several of the tests use the syntaxnew Foo().bar
. However,new
behaves as Pickels had expected in those circumstances. So although this answer is not the solution to the stated problem, here's a review for posterity's sake:When you write
you're referencing the
B
property of a newA
instance.But if you write
(or just
new A.B
—CoffeeScript implicitly adds parentheses at the end of thenew
target if they're absent) then you're creating a new instance ofA.B
. This gets pretty confusing—what'snew A().B()
?—because thenew
operator has its own special precedence rules. So, I recommend using parentheses to clarify such code, e.g.There was discussion here about trying to make this behavior more intuitive in CoffeeScript, but after an energetic effort, it was determined that "the cure was worse than the disease."
让我再试一次:现在,您有三个测试失败。让我们弄清楚如何解决每个故障。
测试 #1
由于缺少
id
,因此出现错误。我将保留该错误的测试,并重写测试 #1 以声明一个合法的、无错误的
Node
实例,就像您对id
测试行所做的那样:这没什么错。每次测试非错误行为时,都应该正确实例化;在本例中,这意味着传递名称和 ID。
测试#2
这与测试#1 基本相同。事实上,我想说你实际上在这里测试得太彻底了。您应该问的问题是:我是否有理由相信将
'bar'
作为名称而不是'foo'
传递会产生不同的行为?我会说“不”。因此,我要么直接删除
'bar'
测试,要么将'bar'
替换为''
(假设您希望允许空字符串作为名称),因为错误放置了or
而不是?
,或者if name
而不是if name?
,可能会导致''
的行为与长度 > 的字符串不同0.测试 #3
此测试失败,因为
() -> new Node() 定义了一个函数——一个永远不会运行的函数。我认为你的意思是只写
new Node()
。其他想法
查看 Speks 文档,听起来首选样式是使用以下命令减少了重复的实例声明代码
beforeEach
。当然,当您测试构造函数本身时,这将不起作用,但您可能希望在将来的大部分测试中使用它。这是测试套件的重写版本,其中包含所有这些建议,并将测试分为三种类型:创建异常的测试、预期正常行为的测试以及对象应该行为正常的测试但这是一种边缘情况:
Let me try this again: Right now, you have three tests that are failing. Let's figure out how to address each failure.
Test #1
This is getting an error because
id
is missing. I would keep the test for that error,and rewrite test #1 to declare a legit, error-free
Node
instance, just as you do with theid
test lines:There's nothing wrong with that. Every time you're testing for non-error behavior, you should be instantiating properly; in this case, that means passing a name and an id.
Test #2
This is basically the same as test #1. In fact, I'd say you're actually testing too thoroughly here. The question you should be asking is: Do I have reason to believe that passing
'bar'
as a name instead of'foo'
will produce a different behavior? I'd say "no."So I'd either remove the
'bar'
test outright, or replace'bar'
with''
(assuming that you want to allow empty strings as names), since a misplacedor
instead of?
, orif name
instead ofif name?
, could cause''
to behave differently than a string of length > 0.Test #3
This test is failing because
() -> new Node()
defines a function—a function which is never run. I think you mean to write justnew Node()
instead.Other thoughts
Looking at the Speks docs, it sounds like a preferred style is cut down on repeated instance declaration code using
beforeEach
. Of course, this won't work when you're testing the constructor itself, but you may want to use it for the bulk of your tests in the future.Here's a rewritten version of your test suite incorporating all of these suggestions and dividing the tests into three types: Those where an exception is created, those where normal behavior is expected, and those where the object should behave properly but is an edge case: