相当于 Ruby 1.9.2 Test::Unit 中 nUnit 的 TestCase
不久前,当我决定学习 Ruby 时,我还决定开始使用单元测试和 TDD 方法。我开始使用 Test::Unit 并编写了几个非常小的类来了解一般的单元测试,特别是 Ruby 和 Test::Unit。
到目前为止,一切都很简单,但后来我想做一些类似于 nUnit 的 TestCase 的事情,因为我进行了 20 个测试,其中唯一改变的是输入和输出。
代码如下所示:
def test_2_inserted_return_true
actual = @prime_generator.is_prime?(2)
assert_equal(true, actual)
end
def test_3_inserted_return_true
actual = @prime_generator.is_prime?(3)
assert_equal(true, actual)
end
def test_5_inserted_return_true
actual = @prime_generator.is_prime?(5)
assert_equal(true, actual)
end
从 DRY 的角度来看,这是相当可怕的。我想要的是类似于 nUnit 的 TestCase 的东西。
像这样的事情:
[TestCase(2.5d, 2d, Result=1.25d)]
[TestCase(-2.5d, 1d, Result = -2.5d)]
public double ValidateDivision(double numerator, double denominator)
{
var myClass = new MyClass();
return myClass.Divide(numerator,denominator);
}
我尝试过谷歌搜索,但找不到有关 Test::Unit 的任何信息。我在 RSpec 和 Selenium 上找到了一些,但这并没有真正帮助我。我也尝试在这里搜索,但也找不到任何东西。
我想过让测试方法接受参数,但再次像这样定义方法......对此不满意。此外,如果我没记错的话,这甚至是不可能的(我现在无法测试,或者我会测试)。
所以,我的问题是:是否可以使用 Ruby (1.9.2) 中的 Test::Unit 进行数据驱动测试?如果不能那么什么框架可以做到这一点?
When I decided to learn Ruby a short while ago I also decided that I'd start using unit tests and the TDD methodology. I started out using Test::Unit and wrote a couple of very small classes to get a feel for unit testing in general and Ruby and Test::Unit in particular.
So far everything has been quite easy but then I wanted to do something similar to nUnit's TestCase as I had 20 tests where the only thing that changed was the input and output.
The code looks like this:
def test_2_inserted_return_true
actual = @prime_generator.is_prime?(2)
assert_equal(true, actual)
end
def test_3_inserted_return_true
actual = @prime_generator.is_prime?(3)
assert_equal(true, actual)
end
def test_5_inserted_return_true
actual = @prime_generator.is_prime?(5)
assert_equal(true, actual)
end
Which is quite horrible from a DRY-perspective. What I would want is something similar to nUnit's TestCase.
Something like this:
[TestCase(2.5d, 2d, Result=1.25d)]
[TestCase(-2.5d, 1d, Result = -2.5d)]
public double ValidateDivision(double numerator, double denominator)
{
var myClass = new MyClass();
return myClass.Divide(numerator,denominator);
}
I've tried googling but could not find anything about Test::Unit. I've found some on RSpec and Selenium but that doesn't really help me. I also tried searching here but couldn't find anything either.
I thought about making the test method take parameters but defining methods again like that... Not happy about it. Besides, if I remember correctly it wasn't even possible (I am not able to test now or I would).
So, my question is: Is it possible to do data driven testing with Test::Unit in Ruby (1.9.2)? If not then what frameworks can do it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我们不要忘记好的循环:
有些人会使用元编程来定义单独的测试方法,但在这种情况下,我认为这是矫枉过正:
通常,我认为测试不应该是 DRY。它们应该是 DAMP(描述性且有意义的短语)。毕竟,测试是您的规范和文档,并且它们是由可能不熟悉 Ruby 甚至一般编程的人阅读的。所以,我什至不确定你原来的例子是坏的,特别是如果你像上面那样清理它:
这就是我所做的:
assert
而不是assert_equal
:检查是否等于true
几乎从来都不是一个好主意,并且assert
< em>已经检查了结果是否真实,那为什么还要麻烦呢?@prime_generator
重命名为@primality_tester
,因为它不会生成素数,它只检查一个数字是否是素数。is_prime?
重命名为prime?
,因为问号已经暗示了这个问题但是,在我看来,最佳解决方案将是这样的:
其中存在重复,但正是重复保持测试的可读性和发音是必要的。 DRY 对于生产代码来说是一个很好的原则,它会不断发展和扩展,但对于测试来说,DRY 始终需要与 DAMP 进行平衡。 (也许编写自定义断言是有意义的,但我对此表示怀疑。至少我无法想出一个好的名称,这始终是一个提示。)
一种完全不同的方法将是基于属性的检查,类似于 Haskell 的 QuickCheck 或 .NET 的 Pex。 QuickCheck 有一个 Ruby 端口,名为 RushCheck,但它自 2006 年以来一直无人维护,维护工作只进行了几次几周前,仍然有很多工作要做,以加快最新版本 Ruby 的速度。
Let's not forget about good ol' loops:
Some people would use metaprogramming to define separate test methods, but in this case I think it's overkill:
Generally, I don't think tests should be DRY. They should be DAMP (descriptive and meaningful phrases). After all, tests are your specification and your documentation, and they are read by people who may not be familiar with Ruby or even programming in general. So, I'm not even sure that your original example is bad, especially if you clean it up a bit like I did above:
Here's what I did:
assert
instead ofassert_equal
: Checking for equality totrue
is almost never a good idea anyway, andassert
already checks that the result is truthy, so why bother?@prime_generator
to@primality_tester
, since, well, it doesn't generate primes, it only checks whether a number is prime.is_prime?
to justprime?
, since the question is already implied by the question markHowever, the best solution IMO would be something like this:
There's duplication in there, but it is duplication that is necessary to keep the test readable and pronouncable. DRY is a good principle for production code, which evolves and is extended, but for tests, DRY always needs to be balanced against DAMP. (Maybe it would make sense to write a custom assertion, but I doubt it. At least I can't come up with a good name for one, which is always a hint.)
A completely different approach would be property-based checking similar to Haskell's QuickCheck or .NET's Pex. There's a Ruby port of QuickCheck called RushCheck, but it has been unmaintained since 2006 and maintenance has only picked up a couple of weeks ago with still a lot of work left to do to get it up to speed on recent versions of Ruby.
您应该检查 rspec 进行单元测试:
运行产量:
You should check out rspec for unit testing:
running yields:
我通过元编程实现了这一点,使用了我在 Jay Fields 博客上找到的一些示例。效果很好,但是对 def_each 的调用必须作为我的测试用例文件的第一行完成。希望这个例子对某人有帮助,很想看到这个答案,但是学习 Define_method 非常酷:)
I did this via metaprogramming, using some samples I found on Jay Fields blog. Worked great, but the call to def_each had to be done as the first line of my test case file. Hope this example helps someone, would have loved to have seen this answer but learning about define_method was pretty cool :)