I spent a good portion of today looking at integration tests.
In the normal course of things, a website undergoes integration tests from an external source; in my career it’s something like selenium for external testing of a website, and faraday for testing a RESTful API.
I’ve been thinking a lot, though, about where selenium fits into the test cycle. There’s a kind of test that I’ve seen selenium used for a lot, but is not its strong point, and that’s testing simple workflows: does /blogpost/new contain a title string, or does /index contain a sign_in link? Selenium _can_ do these things, but I think its real strong suit is complex scenarios: can I log in, then create a blog post, then assign the post to a calendar date, then make sure that the calendar picker doesn’t let me assign two posts to a date, and so on. Lots of steps, each of which takes you further into the application.
Simple stuff like checking if the front page is actually present can absolutely be covered by selenium, but it seems like I see two problems:
- selenium tests take a real time to maintain, even for relatively simple changes.
- selenium can be integrated into the build system, but it’s hard to integrate it into the testing cycle in such a way that developers get feedback before committing their code.
I wanted to solve both of these, and in rails it looks like the built in integration test stuff really solves both in a neat way. It sits there, between the unit test stuff and the full blown complex testing scenarios, providing a simple to maintain, integrated set of tests that nonetheless can be very useful.
Here’s a few downright useful tests I put together with a hand from a couple of guys with more UI experience than I have. Start by generating the integration test:
rails generate integration_test blogs
Now, here’s a neat set of simple tests:
class BlogTest < ActionDispatch::IntegrationTest test "browse index" do get "/" assert_response :success assert_select "h1" end test "browse new page" do get "/blogs/new" assert_response :success assert_select "input" end test "Find some specific field" do get "/blogs/new" assert_response :success assert_select "div.field" end test "Find some specific text area" do get "/blogs/new" assert_response :success assert_select "textarea[name='blog[body]']" end end
If you’ve already installed capybara, the syntax is a little different but not bad:
describe "GET /blogs" do it "works! (now write some real specs)" do # Run the generator again with the --webrat flag if you want to use webrat methods/matchers visit new_blog_path fill_in "Title", with: "Jamandbees' awesome blogness" fill_in "Body", with: "Jamandbees writes about sadness" click_button "Create Blog" page.should have_content "Blog was successfully created." page.should have_content "blogness" end end
That’s literally all there is to some very basic integration tests in rails.
I’m a professional QA resource; my idea about QA is that a QA person should know and understand the stack they’re working with as well as the developers understand it, and be able to comment effectively and, yes, write code in the same language the developers are working in. As a QA person working in rails, I have known the full stack back to back in a basic way, sufficient to be able to sit down, read code with developers and comment upon it with them. If you can’t code review the codebase, there are entire stacks and oodles of bugs you cannot find.
I gave a presentation today about integration testing in rails and got clearance to start writing some of the basic integration tests that will improve our codebase. I can write these, have them integrated in the build and be confident that my (frankly, excellent) team of colleagues in development will be able to maintain them. I think that when an application is still young and in flux, having the QA person write tests and developers easily maintain them is a good balance for the team.