Recently I came across a post that called out a perceived lack of available documentation and other learning material for Minitest in contrast with RSpec. And while I’m not entirely sure I agree with the premise, the main point of the article had the ring of truth to it:
If there’s a problem to be solved here, it’s that the obvious parts of Minitest need to be better documented. Organize the new documentation in the format of “I want to do xyz thing”,with an example.
Honestly, what project couldn’t use better docs - more focused, more examples, and detailed explanations? That was exactly the same line of thinking that got me thinking about writing The Minitest Cookbook.
I released a cheat sheet with the book that I thought might provide people with a partial solution, so I prepared a simplified version that includes a reference to the basic methods and syntax for Minitest and Minitest::Spec as well as a full listing of all assertions and expectations for each along with simple code examples for context. (The full version also includes Rails-specific helpers and assertions and a list of the most commonly used Capybara methods.)
When it was released in Rails 4.2, Active Job was an important addition to the platform. Background jobs have been a part of the ecosystem for a long time, but this was the first time that developers had a single API to work with a variety of job queuing frameworks. Having a common interface has led to a shared base of knowledge and patterns for developing and testing workers.
In the last post, we looked at some good practices for writing well-designed background jobs in Rails using Active Job, but we didn’t get around to the question of how to test them. This post will focus on a step-by-step strategy for testing all of your application’s “set it and forget it” code - one that leverages the unified Active Job interface and the tools Rails and Minitest provide us.
The ability to run operations with long or uncertain execution times in the background has become a standard tool for modern web applications, and most frameworks and platforms now include some sort of support for encapsulating pieces of logic that involve heavy lifting out of the main request/response cycle. For example, I recently finished work on a relatively simple Rails application that had about a dozen different background jobs written for a whole range of standard-ish use cases:
- Sending bulk notifications to a group of users
- Consuming data from external APIs and updating the database
- Batch creation of work items to users
- Importing records from an uploaded data file
- Complex object state manipulation that doesn’t fit in an AR callback
- Refreshing scores cached in the database after an admin changes the weights used to calculate them
The way I write and test background workers has evolved over the years, and since I’m getting ready to start a new project that will have a big background processing component, I thought it would be a good time to reflect on my approach and what I’ve learned.
I just finished reading Jared Friedman’s Why I wouldn’t use rails for a new company. Mr. Friedman is the founding CTO of Scribd which means he’s overseen the development of one of the biggest Rails-based applications on the web, and he’s been notably ahead of the curve on important matters of technology (Scribd’s transition from Flash to HTML5) and policy (SOPA). In short, when he says something about building businesses on the back of Rails-based software, it’s probably worth paying attention.
Which is probably why I found reading this article so frustrating. I expected a well-informed argument combining technology- and business-oriented reasons that Rails was no longer where it’s at, but what I got was a mixture of opinion and cherry-picked facts that were at best selective and at worst intentionally misleading. It was a missed opportunity to have a serious discussion about the directions of Ruby and Rails as technologies and the factors that businesses should consider when deciding what tools to use when building out their applications.
I still like Rails for new application development - not just because of the time I’ve spent learning the framework, but because I still believe Rails is a force multiplier for software development. In this response to Mr. Friedman’s piece, I want to examine the points he made in more detail, calling bullshit where necessary, and then add my two cents to the discussion by assessing what Rails does right and where it can still improve.
The most popular methods for learning Ruby on Rails today all place testing front and center. The Ruby on Rails Tutorial incorporates sections on testing in almost every chapter as does Agile Web Development with Rails 4. Other popular Rails books concentrate most of their testing material in one or two chapters, but I don’t know of any important teaching resource that ignores it entirely.
But even though a culture of testing runs deep within the community and is the modus operandi in most large Rails shops, certain essential concepts that remain elusive to many. Take the differences between the types of tests usually found in Rails applications as an example. Most programmers can clearly explain the differences between model and controller tests, but ask about controller tests versus integration tests, and you’ll probably get a mixture of confusion and shrugs.