Test-driven development workflow in Ruby - Time & Space Complexity
We want to understand how the time spent changes when following the test-driven development workflow in Ruby.
How does the number of tests and code changes affect the time it takes to run tests repeatedly?
Analyze the time complexity of this simple test-driven development cycle.
require 'minitest/autorun'
class Calculator
def add(a, b)
a + b
end
end
class TestCalculator < Minitest::Test
def test_add
calc = Calculator.new
assert_equal 5, calc.add(2, 3)
end
end
This code defines a simple Calculator class and a test that checks the add method.
In test-driven development, the main repeating operation is running the test suite.
- Primary operation: Running all tests after each code change.
- How many times: Once per code change, repeated many times during development.
As the number of tests grows, the time to run all tests grows too.
| Input Size (number of tests) | Approx. Operations (test runs) |
|---|---|
| 10 | 10 test runs per cycle |
| 100 | 100 test runs per cycle |
| 1000 | 1000 test runs per cycle |
Pattern observation: The time to run tests grows roughly in direct proportion to the number of tests.
Time Complexity: O(n)
This means the time to run all tests grows linearly with the number of tests.
[X] Wrong: "Running one test is always fast, so adding more tests won't slow things down much."
[OK] Correct: Each test adds time, so many tests add up and make the total test run longer.
Understanding how test suite size affects development speed helps you write better tests and manage time well in real projects.
"What if we only run tests related to changed code instead of all tests? How would the time complexity change?"
Practice
Solution
Step 1: Understand the TDD cycle
The TDD cycle starts by writing a test that fails because the feature is not implemented yet.Step 2: Identify the first action in TDD
Writing a failing test first guides the development and ensures the code meets requirements.Final Answer:
Write a failing test that defines the desired behavior -> Option BQuick Check:
First step in TDD = Write failing test [OK]
- Starting by writing implementation code before tests
- Refactoring before any test is written
- Running tests before any code or test exists
Solution
Step 1: Identify the test framework command
Minitest tests are run by executing the Ruby test file directly withruby test_file.rb.Step 2: Eliminate unrelated commands
rspecis for RSpec tests,rails serverstarts the server, andbundle installinstalls gems.Final Answer:
ruby test_file.rb -> Option CQuick Check:
Run Minitest with ruby test_file.rb [OK]
- Using rspec command for Minitest tests
- Confusing server start with test run
- Running bundle install instead of tests
require 'minitest/autorun'
class Calculator
def add(a, b)
a + b
end
end
class TestCalculator < Minitest::Test
def test_add
calc = Calculator.new
assert_equal 5, calc.add(2, 3)
end
endSolution
Step 1: Analyze the test and method
Theaddmethod returns the sum of two numbers. The test expects 5 from adding 2 and 3.Step 2: Check if test passes
Since 2 + 3 equals 5, the assertion passes and the test succeeds.Final Answer:
1 test, 0 failures -> Option AQuick Check:
Correct sum = test passes [OK]
- Thinking test fails when it actually passes
- Confusing syntax error with test failure
- Ignoring the assert_equal expected value
class TestCalculator < Minitest::Test
def test_multiply
calc = Calculator.new
assert_equal 6, calc.multiply(2, 3)
end
end
class Calculator
def multiply(a, b)
a - b
end
endSolution
Step 1: Compare method implementation with test expectation
The test expectsmultiply(2, 3)to return 6, but the method subtractsa - b.Step 2: Identify the error cause
Subtracting 2 - 3 gives -1, which will fail the test expecting 6.Final Answer:
The multiply method subtracts instead of multiplies -> Option DQuick Check:
Method logic must match test expectation [OK]
- Confusing subtraction with multiplication
- Ignoring method implementation details
- Assuming test method name affects test result
Solution
Step 1: Understand the role of refactoring in TDD
Refactoring means improving code structure without changing behavior, done safely with tests as a safety net.Step 2: Identify the correct practice
Running tests frequently during refactoring ensures no functionality breaks.Final Answer:
Refactor the code while running tests frequently -> Option AQuick Check:
Refactor + frequent tests = safe improvements [OK]
- Running tests only after all changes
- Deleting tests which protect code quality
- Writing tests after refactoring instead of before
Ready to prove it?
Pass the test and this pattern moves unknown
