82

我正在通过在 Ruby 中编写与 Kent Beck 的 xUnit 等效的代码来扩展我对 Ruby 的理解。Python(由 Kent 编写)在广泛使用的语言中有一个 assert() 方法。红宝石没有。我认为添加它应该很容易,但是内核是放置它的正确位置吗?

顺便说一句,我知道 Ruby 中存在各种 Unit 框架——这是一个学习 Ruby 习语的练习,而不是“完成某事”。

4

5 回答 5

117

不,这不是最佳做法。与 Ruby 中的 assert() 最好的类比就是提高

 raise "This is wrong" unless expr

如果您想提供更具体的异常处理,您可以实现自己的异常

于 2009-08-11T16:08:15.127 回答
32

我认为在 Ruby 中使用断言是完全有效的。但是您提到了两件事:

  • xUnit 框架使用assert方法来检查您的测试期望。它们旨在用于您的测试代码,而不是您的应用程序代码。
  • 某些语言(如 C、Java 或 Python)包含assert旨在用于程序代码内部的构造,以检查您对其完整性所做的假设。这些检查是在代码本身内部构建的。它们不是测试时实用程序,而是开发时实用程序。

我最近写了solid_assert:一个实现 Ruby 断言实用程序的小型 Rub​​y 库,并且在我的博客中发表了一篇解释其动机的文章。它让您可以编写以下形式的表达式:

assert some_string != "some value"
assert clients.empty?, "Isn't the clients list empty?"

invariant "Lists with different sizes?" do
    one_variable = calculate_some_value
    other_variable = calculate_some_other_value
    one_variable > other_variable
end    

并且它们可以被停用assert并被invariant评估为空语句。这可以让您避免生产中的任何性能问题。但请注意,实用程序员建议不要停用它们。只有当它们确实影响性能时,您才应该停用它们。

关于回答说惯用的Ruby方式是使用普通raise语句的答案,我认为它缺乏表现力。断言编程的黄金法则之一是不使用断言进行正常的异常处理。它们是两种完全不同的东西。如果你对它们两个使用相同的语法,我认为你的代码会更加晦涩难懂。当然,您将失去停用它们的能力。

您可以确信使用断言是一件好事,因为两本必读的经典书籍,如The Pragmatic Programmer From Journeyman to MasterCode Complete将整个部分专门用于它们并推荐使用它们。还有一篇名为Programming with assertions的好文章很好地说明了断言编程的内容以及何时使用它(它基于 Java,但概念适用于任何语言)。

于 2011-09-20T07:05:37.670 回答
15

您将 assert 方法添加到内核模块的原因是什么?为什么不直接使用另一个名为Assertions或其他的模块?

像这样:

module Assertions
  def assert(param)
    # do something with param
  end

  # define more assertions here
end

如果您真的需要您的断言随处可用,请执行以下操作:

class Object
  include Assertions
end

免责声明:我没有测试代码,但原则上我会这样做。

于 2008-09-29T14:34:07.640 回答
9

这不是特别地道,但我认为这是一个好主意。特别是如果这样做:

def assert(msg=nil)
    if DEBUG
        raise msg || "Assertion failed!" unless yield
    end
end

这样,如果您决定不使用 DEBUG(或其他一些方便的开关,我过去使用过 Kernel.do_assert)设置运行,则不会产生任何影响。

于 2010-06-03T13:02:59.133 回答
5

我的理解是,您正在编写自己的测试套件,以此来更加熟悉 Ruby。因此,虽然 Test::Unit 可能作为指南有用,但它可能不是您想要的(因为它已经完成了工作)。

也就是说,python 的 assert (至少对我而言)更类似于 C 的assert(3)。它不是专门为单元测试设计的,而是为了捕捉“这永远不会发生”的情况。

那么,Ruby 的内置单元测试如何看待问题是,每个单独的测试用例类都是TestCase的子类,其中包括一个“断言”语句,该语句检查传递给它的内容的有效性并记录它报告。

于 2008-09-29T21:04:54.500 回答