
A new take on TDD
I like to apply Test Driven Development (TDD) to my sysadmin and security work. Every time I add a new redirect to a web server, I want to ensure I didn’t break something else.

Further, I want my SSL configurations proactively checked daily for any possible error. I use Ruby RSpec and write tests like these:
describe 'My app' do
context 'www.myapp.com' do
it { should be_up }
it { should have_a_valid_cert }
end
it 'serves the www.myapp.com page without redirecting' do
expect('http://www.myapp.com/about').to be_status 200
end
it 'only serves via www' do
expect('http://myapp.com').to redirect_permanently_to 'http://www.myapp.com/'
end
it 'forces visitors to use https' do
expect('myapp.com').to enforce_https_everywhere
end
end
I created these new functions to help write these tests : be_up, have_a_valid_cert, be_status, redirect_permanently_to, and enforce_https_everywhere.
Step 1: Write a failing test
When I want to make a configuration change, I first write a new test for the desired outcome. I literally think to myself, “How do I want my app to work?” The test should demonstrate that. Naturally, it fails while the old tests pass.
Step 2: Make the firewall/Linux/whatever configuration work
Then I work on the config change. I re-run all the tests as I go. I am finished when they all pass. (Extra benefit: I know when to stop working!) I also run these automatically from a cron job to get pro-active notification of new problems.
Step 3: Clean up and document
All the tests are passing. That means I have a nice “safety net.” It lets me clean up and reorganize my configurations if they need it.
The phrases like have_a_valid_cert are custom RSpec matchers; they’re added into the RSpec environment by my open source library on Github.
Leave a comment