Search code examples
ruby-on-railsrspecrspec-railsrspec3

is it good to use global variables in specs?


is it good to use global variables in specs?

I want to use this var in my tests. And define it in spec_helper.rb

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

Is this a good idea or not? and why?


Solution

  • Global variables are discouraged, in RSpec, and in general. Here's why:

    Modifying a global variable anywhere affects code everywhere.

    So, if a test ever modified the $now variable, all subsequent tests would be affected by the modification. This could lead to some very hard to debug test failures. Hard to debug, because the test would be correct. But, the value of the global would not. So, you could not find the bug in the tests by simple inspection. You'd have to debug it at runtime.

    Automated tests need to be independent of each other. This is why RSpec has the lazily executed let statement. let allows you to define a variable within the context of a single example. Here's what the RSpec docs say:

    Use let to define a memoized helper method. The value will be cached across multiple calls in the same example but not across examples.

    What this means is that if you define now like this:

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

    The value is guaranteed to be exactly what you say it is in every single test. Because the value is memoized on a per example basis, one test can never affect the value that another test receives when executing.

    If you're still not convinced, I would recommend using a global constant over a global variable. At least then, Ruby would warn you if you tried to change the value.