Guards

Version 1 (Federico Builes, 08/24/2008 07:01 PM)

1 1
h2. MSpec guards
2 1
3 1
h3. platform_is
4 1
5 1
In some cases, Ruby exhibits different behaviors based on its execution environment. For example, the maximum value of a Fixnum before it is promoted to a Bignum is different in 32-bit and 64-bit platforms. In this cases you can use the
6 1
platform_is guard:
7 1
8 1
9 1
  platform_is :wordsize => 32 do
10 1
    it "converts numbers to Bignums if they get too big" do
11 1
       # 32-bit behaviour goes here
12 1
    end
13 1
  end 
14 1
  
15 1
  platform_is_not :os => :windows do
16 1
    it "runs on a real OS"
17 1
      # do something...
18 1
    end
19 1
  end
20 1
21 1
22 1
This would "do something" on every OS but Windows.
23 1
24 1
h3. compliant_on/non_compliant_on
25 1
26 1
Since each Ruby implementation may have its own quirks, you can make use of the @compliant_on/non_compliant_on@ set of guards to make sure that your specs run only on certain implementations:
27 1
28 1
29 1
  non_compliant_on :jruby do
30 1
    # some code that works differently in JRuby
31 1
  end
32 1
33 1
34 1
Since we're using this project to specify the behavior of MatzRuby (MRI), every @compliant_on@ guard should include @:ruby@ and no @non_compliant_on@ should have it.
35 1
36 1
h3. ruby_bug
37 1
38 1
If you know that a certain version of Ruby has a bug and you want to guard against it you can use the @ruby_bug@ guard:
39 1
40 1
41 1
  ruby_bug "some_id_number", version do
42 1
    it "produces 2 when adding 1 to 1" do
43 1
      # CORRECT implementation goes here
44 1
      (1 + 1).should == 2
45 1
    end
46 1
  end
47 1
48 1
49 1
In this case, @some_id_number@ is the number of the reported issue in "Ruby's Redmine tracker":http://redmine.ruby-lang.org/ (because you did create an issue for this, right?). @version@ is the Ruby version you want to guard against, for example:
50 1
51 1
52 1
  ruby_bug "#1337", 1.8.6.110 do
53 1
    it "produces 2 when adding 1 to 1" do
54 1
      (1+1).should == 2
55 1
    end
56 1
  end
57 1
58 1
59 1
In this case the issue was reported in Ruby's Redmine as ticket #1337 and this spec will be ignored when the Ruby version is ruby-1.8.6 patchlevel 110.
60 1
61 1
h3. ruby_version_is
62 1
63 1
Sometimes the behavior of certain methods will change between different Ruby versions (or revisions). If you're writing specs against several patchlevels or releases you can use the @ruby_version_is@ guard:
64 1
65 1
66 1
  ruby_version_is "" ... "1.9" do
67 1
    it "adds two numbers" do
68 1
      (1+1).should == 2
69 1
    end		
70 1
  end
71 1
72 1
  ruby_version_is "1.9" do
73 1
    it "adds two numbers" do
74 1
      (1+1).should == 3
75 1
    end		
76 1
  end
77 1
78 1
79 1
In this case we're assuming that 1 + 1 will equal 2 in every version *before* 1.9 and that in 1.9 and *following* versions it will return 3.
80 1
81 1
h3. big_endian/little_endian
82 1
83 1
h3. as_superuser
84 1
85 1
If you need to make sure that you're root before running some of your specs you can use the @as_superuser@ guard:
86 1
87 1
88 1
  as_superuser do
89 1
    it "is dangerous" do
90 1
      FileUtils.rm_rf("/")
91 1
    end
92 1
  end
93 1
94 1
95 1
If the user running the specs is not root (UID = 0) the specs will be ignored.
96 1
97 1
h3. not_supported_on
98 1
99 1
If a Ruby implementation does not support a certain feature (and probably won't support it in the future) you can use the @not_supported_on@ guard:
100 1
101 1
102 1
  not_supported_on :rubinius do
103 1
    it "does some crazy stuff that rubinius people seem to hate" do
104 1
    end 
105 1
  end		   
106 1
107 1
108 1
Please note that this guard should only be used when you're almost certain that a feature won't be supported in a Ruby implementation. If you intend to guard a certain case while the implementation supports it you're better off using the MSpec tagging mechanism.
109 1
110 1
If the implementation you're specifying differs from MRI you should use the @non_compliant_on@ guard.
111 1
112 1
h3. conflicts_with
113 1
114 1
If you want to make sure that another class or module is not defined in the current scope before running some tests you can use the @conflicts_with@ guard:
115 1
116 1
117 1
  conflicts_with :SomeWeirdClass do
118 1
    it "will not be run if SomeWeirdClass is defined" do
119 1
      ...
120 1
    end
121 1
  end
122 1
123 1
124 1
In this case the spec will run only if SomeWeirdClass is not currently defined. It won't run if SomeWeirdClass is part of the Core classes, if it was required/included or if it was defined earlier.
125 1
126 1
h3. extended_on
127 1
128 1
129 1
h3. runner_is/runner_is_not
130 1
131 1
In some cases you might want to make sure that a set of specs runs only under a certain runner (rSpec or MSpec). You can use the @runner_is@/@runner_is_not@ guards to check this:
132 1
133 1
134 1
  runner_is :rspec do
135 1
    it "does something that only runs under rSpec" do
136 1
      ...
137 1
    end
138 1
  end
139 1
140 1
  runner_is :mspec do
141 1
    it "does something that only runs under MSpec" do
142 1
      ...
143 1
    end
144 1
  end
145 1
146 1
147 1
h3. quarantine!
148 1
149 1
This guard will always return false, which means that the cases inside it will *never* be run. There are only a handful of acceptable uses for this guard, so please make sure to check on IRC before using it:
150 1
151 1
152 1
  quarantine! do 
153 1
    it "will never be run" do
154 1
      ...
155 1
    end
156 1
  end
157 1