【问题标题】:is it good to use global variables in specs?在规范中使用全局变量好吗?
【发布时间】:2019-02-27 16:03:15
【问题描述】:

在规范中使用全局变量好不好?

我想在我的测试中使用这个变量。并定义在spec_helper.rb

$now = DateTime.parse('2020-01-01 00:00:01 -0500')

这是个好主意吗?为什么?

【问题讨论】:

    标签: ruby-on-rails rspec rspec-rails rspec3


    【解决方案1】:

    在 RSpec 和一般情况下,不鼓励使用全局变量。原因如下:

    在任何地方修改全局变量都会影响任何地方的代码。

    因此,如果某个测试曾经修改过$now 变量,那么所有后续测试都会受到修改的影响。这可能会导致一些非常难以调试的测试失败。很难调试,因为测试是正确的。但是,全球的价值不会。因此,您无法通过简单的检查在测试中找到错误。您必须在运行时对其进行调试。

    自动化测试需要相互独立。这就是 RSpec 延迟执行 let 语句的原因。 let 允许您在单个示例的上下文中定义变量。 RSpec docs 是这样说的:

    使用 let 定义一个记忆化的辅助方法。该值将被缓存 在同一个示例中多次调用,但不是跨示例。

    这意味着如果你这样定义now

    let(:now) { DateTime.parse('2020-01-01 00:00:01 -0500') }
    

    保证该值与您在每个测试中所说的完全相同。因为值是基于每个示例进行记忆的,所以一个测试永远不会影响另一个测试在执行时收到的值。

    如果您仍然不相信,我建议您在全局变量上使用全局常量。至少那时,如果您尝试更改该值,Ruby 会警告您。

    【讨论】:

    • 此外,您可以使用 Timecop gem 在您的规范中以确定性的方式处理时间。
    【解决方案2】:

    这是个坏主意。实际上,您应该避免在代码的任何地方使用全局变量。

    您可以使用 before 块来设置需要与测试示例一起使用的任何变量。

    例子:

    describe Thing do
      before(:each) do
        @now = DateTime.parse('2020-01-01 00:00:01 -0500')
      end
    
      describe "initialized in before(:each)" do
        it "example 1" do
          // here @now is available
        end
    
        it "example 2" do
          // here @now is also available
        end
      end
    end
    

    【讨论】:

    • 但是如果我有很多这样的地方呢?我觉得每次写before块并确定时间也不好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 1970-01-01
    • 2017-12-30
    • 1970-01-01
    • 2014-12-23
    • 1970-01-01
    • 2020-04-25
    相关资源
    最近更新 更多