RSpec expectations and matchers in Ruby - Time & Space Complexity
When using RSpec expectations and matchers, it helps to know how the time to check conditions grows as tests run.
We want to see how the number of checks changes when we test more items or more complex conditions.
Analyze the time complexity of the following RSpec test code.
describe 'Array content' do
it 'checks all elements are even' do
array = (1..n).to_a
array.each do |num|
expect(num.even?).to be true
end
end
end
This code tests if every number in an array is even by checking each element one by one.
Look for loops or repeated checks in the test.
- Primary operation: The
eachloop runs through every element in the array. - How many times: It runs once for each element, so
ntimes if the array hasnitems.
As the array gets bigger, the number of checks grows too.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 checks |
| 100 | 100 checks |
| 1000 | 1000 checks |
Pattern observation: The number of checks grows directly with the number of items. Double the items, double the checks.
Time Complexity: O(n)
This means the time to run the test grows in a straight line with the number of elements checked.
[X] Wrong: "The test runs in constant time no matter how many elements there are."
[OK] Correct: Each element is checked separately, so more elements mean more checks and more time.
Understanding how test checks grow helps you write efficient tests and explain your reasoning clearly in interviews.
"What if we used a matcher that stops checking after the first failure? How would the time complexity change?"
Practice
expect(value).to eq(5) check for?Solution
Step 1: Understand the
Theeqmatchereqmatcher tests for equality between the expected and actual values.Step 2: Analyze the expectation
expect(value).to eq(5)means the test expectsvalueto be exactly 5.Final Answer:
It checks ifvalueis equal to 5. -> Option DQuick Check:
eq matcher = equality check [OK]
- Confusing eq with greater_than or less_than
- Thinking eq checks for inequality
- Mixing up expect().to and expect().not_to
Solution
Step 1: Identify the correct matcher for inclusion
Theincludematcher checks if a collection contains a specific element.Step 2: Match syntax with RSpec standards
expect(array).to include(3)is the correct syntax to check if 3 is in the array.Final Answer:
expect(array).to include(3) -> Option BQuick Check:
include matcher = check element presence [OK]
- Using has or contains which are not valid RSpec matchers
- Using has_key which is for hashes, not arrays
- Forgetting to use expect().to syntax
describe 'Number test' do
it 'checks if number is odd' do
number = 7
expect(number.odd?).to be true
end
endSolution
Step 1: Understand the code logic
The variablenumberis set to 7, which is an odd number.Step 2: Analyze the expectation
expect(number.odd?).to be truechecks ifnumber.odd?returns true, which it does for 7.Final Answer:
The test passes because 7 is odd. -> Option AQuick Check:
odd? returns true for odd numbers [OK]
- Assuming 7 is even
- Confusing be true with eq true
- Thinking syntax is wrong here
expect(user.name).to eq nil
Solution
Step 1: Understand nil checking in RSpec
Whileeq nilworks, the preferred matcher for nil isbe_nilfor clarity and style.Step 2: Identify best practice
Usingexpect(user.name).to be_nilis clearer and idiomatic in RSpec.Final Answer:
Should usebe_nilmatcher instead ofeq nil. -> Option CQuick Check:
Use be_nil for nil checks [OK]
- Thinking eq nil is a syntax error
- Adding unnecessary parentheses
- Using not_to eq nil to check for nil
calculate returns a value greater than 10 but less than 20. Which RSpec expectation correctly checks this?Solution
Step 1: Understand the range requirement
The value must be greater than 10 and less than 20, excluding 10 and 20 themselves.Step 2: Analyze each option
expect(calculate).to be > 10 and be < 20:expect(calculate).to be > 10 and be < 20is invalid syntax; correct chaining uses(be > 10).and(be < 20).
Options C and D:be_betweenis not a built-in RSpec matcher.
expect(calculate).to satisfy { |v| v > 10 && v < 20 }:expect(calculate).to satisfy { |v| v > 10 && v < 20 }correctly checks the condition using a standard flexible matcher.Step 3: Choose the best matcher
expect(calculate).to satisfy { |v| v > 10 && v < 20 } is the correct and explicit choice using standard RSpec.Final Answer:
expect(calculate).to satisfy { |v| v > 10 && v < 20 } -> Option AQuick Check:
satisfy matcher = custom condition check [OK]
- Using non-standard be_between matcher
- Trying to chain matchers with 'and' incorrectly
- Ignoring boundary conditions in range checks
Ready to prove it?
Pass the test and this pattern moves unknown
