index.md (3283B)
1 --- 2 title: "Testing Your Code’s Text" 3 date: 2011-08-31T00:00:00+00:00 4 draft: false 5 canonical_url: https://www.viget.com/articles/testing-your-codes-text/ 6 --- 7 8 The "Ubiquitous Automation" chapter of [*The Pragmatic 9 Programmer*](https://books.google.com/books?id=5wBQEp6ruIAC&lpg=PA254&vq=ubiquitous%20automation&pg=PA230#v=onepage&q&f=false) 10 opens with the following quote: 11 12 > Civilization advances by extending the number of important operations 13 > we can perform without thinking. 14 > 15 > --Alfred North Whitehead 16 17 As a responsible and accomplished developer, when you encounter a bug in 18 your application, what's the first thing you do? Write a failing test 19 case, of course, and only once that's done do you focus on fixing the 20 problem. But what about when the bug is not related to the *behavior* of 21 your application, but rather to its configuration, display, or some 22 other element outside the purview of normal testing practices? I contend 23 that you can and should still write a failing test. 24 25 **Scenario:** In the process of merging a topic branch into master, you 26 encounter a conflict in one of your ERB files. You fix the conflict and 27 commit the resolution, run the test suite, and then deploy your changes 28 to production. An hour later, you receive an urgent email from your 29 client wondering what happened to the footer of their site. As it turns 30 out, there were *two* conflicts in the file, and you only fixed the 31 first, committing the conflict artifacts of the second into the repo. 32 33 Your gut instinct is to zip off a quick fix, write a self-deprecating 34 commit message, and act like the whole thing never happened. But 35 consider writing a rake task like this: 36 37 ```ruby 38 namespace :preflight do 39 task :git_conflict do 40 paths = `grep -lir '<<<\|>>>' app lib config`.split(/\n/) 41 42 if paths.any? 43 puts "ERROR: Found git conflict artifacts in the following files\n\n" 44 paths.each {|path| puts " - #{path}" } 45 exit 1 46 end 47 end 48 end 49 ``` 50 51 This task greps through your `app`, `lib`, and `config` directories 52 looking for occurrences of `<<<` or `>>>` and, if it finds any, prints a 53 list of the offending files and exits with an error. Hook this into the 54 rake task run by your continuous integration server and never worry 55 about accidentally deploying errant git artifacts again: 56 57 ```ruby 58 namespace :preflight do 59 task :default do 60 Rake::Task['cover:ensure'].invoke 61 Rake::Task['preflight:all'].invoke 62 end 63 64 task :all do 65 Rake::Task['preflight:git_conflict'].invoke 66 end 67 68 task :git_conflict do 69 paths = `grep -lir '<<<\|>>>' app lib config`.split(/\n/) 70 71 if paths.any? 72 puts "ERROR: Found git conflict artifacts in the following files\n\n" 73 paths.each {|path| puts " - #{path}" } 74 exit 1 75 end 76 end 77 end 78 79 Rake::Task['cruise'].clear 80 81 task :cruise => 'preflight:default' 82 ``` 83 84 We've used this technique to keep our deployment configuration in order, 85 to ensure that we're maintaining best practices, and to keep our 86 applications in shape as they grow and team members change. Think of it 87 as documentation taken to the next level -- text to explain the best 88 practice, code to enforce it. Assuming you're diligent about running 89 your tests, every one of these tasks you write is a problem that will 90 never make it to production.