Hacker News new | ask | show | jobs
by mattvanhorn 4845 days ago
Here's my work flow:

I write a specification (using RSpec) of some behavior. It fails.

Then I write code to make that specification pass.

Now the code is working correctly, as I have defined it.

Then I refactor, using my specs (tests) as a safety net to ensure that everything after the refactor still works as intended.

This is a _VERY_ different approach than coming up with some solution in my head, implementing it (most likely with bugs), and then using tests to find and eliminate as many bugs as possible (but usually not all of them).

Any errors that make it through to a commit, when I am doing TDD, are errors in how I have specified (or failed to specify) the behavior. Any errors in the design or implementation of the solution are caught by building to a spec in very small steps.

That's the key difference between properly done BDD/TDD and other testing. Writing the tests prevents bugs instead of catching them, and it ensures that behavior does not change after refactoring.

It may be a subtle distinction, but in practice it makes a huge impact.

1 comments

Two questions:

1. What do you about security? How, for example, do you make sure you don't introduce XSS vulnerabilities into your code? To use your words, how does "writing the tests prevent bugs" when we're talking about bugs that create XSS vectors?

2. Don't you think you're paying a penalty by defining and implementing your system's semantics through the pinhole-sized view of one failing test at a time? That is, why wouldn't you be better off defining the semantics in whatever-sized units make the most sense, not necessarily one spec's worth at a time, and then deriving your tests and implementation from the semantics accordingly?