Making It Pass

So, now that we have our solid failing Cucumber scenario in place, it’s time to let that scenario drive out a solution.

There is a very simple solution that will make the test pass, but it’s not going to get us very far. Let’s try it anyway, for fun:

 print ​"4"

Try it. You should see the scenario pass at last:

 ...
 
 1 scenario (1 passed)
 3 steps (3 passed)
 0m0.356s

Hooray! So, what’s wrong with this solution? After all, we already said that we want to do the minimum work that the tests will let us get away with, right?

Actually, that’s not quite what we said. We said we want to do the minimum useful work that the tests will let us get away with. What we’ve done here might have made the test pass, but it isn’t very useful. Apart from the fact that it certainly isn’t going to function as a calculator yet, let’s look at what we’ve missed out on testing with our smarty-pants one-liner solution:

  • We haven’t tried to read the input from the command line.
  • We haven’t tried to add anything up.

In Crystal Clear: A Human-Powered Methodology for Small Teams [Coc04], Alistair Cockburn advocates building a walking skeleton as early as possible in a project to try to flush out any potential problems with your technology choices. Obviously, our calculator is trivially simple, but it’s still worth considering this principle: why don’t we build something more useful that passes this scenario and helps us learn more about our planned implementation?

If you’re unconvinced by that argument, try looking at it as a problem of duplication. We have a hard-coded value of 4 in two places: once in our scenario and once in our calculator program. In a more complex system, this kind of duplication might go unnoticed, and we’d have a brittle scenario.

Let’s force ourselves to fix this, using what Kent Beck calls triangulation (Test-Driven Development: By Example [Bec02]). We’ll add another scenario to our feature, using a new keyword called a Scenario Outline:

 Feature​: Adding
 
 Scenario Outline​: Add two numbers
  Given the input ​"<input>"
  When the calculator is run
  Then the output should be ​"<output>"
 
  Examples:
  | input | output |
  | 2+2 | 4 |
  | 98+1 | 99 |

We’ve turned our scenario into a Scenario Outline, which lets us specify multiple scenarios using a table. We could have copied and pasted the whole scenario and just changed the values, but we think this is a more readable way of expressing the examples, and we want to give you a taste of what’s possible with Gherkin’s syntax. Let’s see what the output looks like now:

 $ ​​cucumber
 Feature: Adding
 
  Scenario Outline: Add two numbers
  Given the input "<input>"
  When the calculator is run
  Then the output should be "<output>"
 
  Examples:
  | input | output |
  | 2+2 | 4 |
  | 98+1 | 99 |
 
  expected: "99"
  got: "4"
 
  (compared using ==)
  (RSpec::Expectations::ExpectationNotMetError)
  ./features/step_definitions/calculator_steps.rb:16
  features/adding.feature:11
 
 Failing Scenarios:
 cucumber features/adding.feature:11
 
 2 scenarios (1 failed, 1 passed)
 6 steps (1 failed, 5 passed)

We can see from the summary 2 scenarios (1 failed, 1 passed) that Cucumber has run two scenarios. Each row in the Examples table is expanded into a scenario when Cucumber runs the scenario outline. The first example—where the result is 4—still passes, but the second example is failing.

Now it definitely makes sense to reimplement our program with a more realistic solution:

 print eval(ARGV[0])

First we read the command-line argument ARGV[0] and send it to Ruby’s eval method. That should be able to work out what to do with the calculation input. Finally, we print the result of eval to the console.

Try that. Do both scenarios pass? Great! You’ve just built your first program with Cucumber.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.217.198