{"id":9604,"date":"2015-12-25T16:11:33","date_gmt":"2015-12-25T14:11:33","guid":{"rendered":"http:\/\/www.webcodegeeks.com\/?p=9604"},"modified":"2015-12-17T19:46:14","modified_gmt":"2015-12-17T17:46:14","slug":"unit-testing-ruby","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/","title":{"rendered":"Unit Testing in Ruby"},"content":{"rendered":"<p>In his <a href=\"http:\/\/martinfowler.com\/bliki\/UnitTest.html\">article on Unit Testing<\/a>, Martin Fowler mentions that what a unit <em>actually<\/em> is can change depending on what school of thought you come from. Many from the object-oriented world consider the Class as the unit, whereas those in the functional programming world consider the Function the unit.<\/p>\n<p>Even though Ruby is an object-oriented language, I tend to see the method\/function as the unit. This is what should be tested, focusing on those methods which comprise the public interface of a particular class. Private methods can be tested through their public interfaces, allowing the actual implementation of them to change and be refactored as needed.<\/p>\n<p>In this article, we\u2019ll look at a number of ways in which we can perform unit testing in Ruby. We\u2019ll look at how we can isolate our units from their dependencies and also how we can verify that our code is working correctly.<\/p>\n<h2>Testing Is Important\u2026 and Opinionated<\/h2>\n<p>You only have to look as far as DHH to see that <a href=\"http:\/\/david.heinemeierhansson.com\/2014\/tdd-is-dead-long-live-testing.html\">with testing come opinions<\/a>.<\/p>\n<p>With testing, there are many good reasons to either push for complete isolation from unit to unit or to allow the system to work together as it was built, with dependencies and all. The most important thing is that you actually <em>do<\/em> test, no matter which methodology you follow.<\/p>\n<p>I am not entirely against testing private methods if it can help the programmer verify that they are working correctly, especially as part of TDD, so it should be left up to the individual to make a decision. Just keep in mind that private implementation is more likely to change than public API \u2014 these tests are more likely to be rewritten and\/or completely thrown out when their usefulness is gone.<\/p>\n<p>Tests and <a href=\"https:\/\/en.wikipedia.org\/wiki\/Test-driven_development\">Test Driven Development<\/a> should help you write better code that you are more confident about. Follow the methodology that helps you achieve that.<\/p>\n<h3>What should be tested?<\/h3>\n<p>Given that we\u2019re going to be testing methods, what do we actually test? What are we trying to prove by testing them? The thing to ask is what the method\u2019s purpose is. That is what should be tested. What does it set out to accomplish?<\/p>\n<p>I imagine there are others, but I am going to group a method\u2019s purpose into three different categories:<\/p>\n<ol>\n<li>It returns a value.<\/li>\n<li>It passes the work along to somewhere else (<em>i.e.<\/em>, dispatches the work elsewhere).<\/li>\n<li>It causes a side effect.<\/li>\n<\/ol>\n<h3>What shouldn\u2019t be tested?<\/h3>\n<p>When unit testing, it is important to avoid testing the entire system (which would be integration testing \u2014 also important). It\u2019s also especially important to avoid external dependencies, among the worst of them being an external API call.<\/p>\n<p>External dependencies can and will fail. You should plan for what would happen if an external API is down, but you shouldn\u2019t be testing that it does its job correctly. Let it worry about that while you focus on what your unit of code is doing.<\/p>\n<p>By avoiding external dependencies you are also helping to speed up your tests. Reading from a file or talking to a database is slow, and talking to an external HTTP API is even slower. Besides, they most likely don\u2019t want you hitting their API every time you (or your CI server) run the test suite.<\/p>\n<h2>Examples of Unit Testing<\/h2>\n<p>The code we are going to use in the following examples involves a number of classes, all relating to a gift card system.<\/p>\n<p>There will be a <code>Giftcard<\/code> class, which in a Rails app would be an <code>ActiveRecord<\/code> model. There will be another class called <code>Giftcards::Repository<\/code>, whose job it is to perform different actions on the gift card such as creating a new one, checking the balance, adjusting the balance, and canceling the gift card. Lastly, we have a number of different adapters whose job it is to talk with the issuer of each gift card.<\/p>\n<p>We\u2019ll work with a <code>Cardex<\/code> adapter and a <code>Test<\/code> adapter (a fake adapter for use in tests).<\/p>\n<pre class=\" brush:php\">class Giftcard\r\n  attr_accessor :card_number, :pin, :issuer, :cancelled_at\r\n\r\n  def self.create!(options)\r\n    self.new.tap do |giftcard|\r\n      options.each do |key, value|\r\n        giftcard.send(\"#{key}=\", value) if giftcard.respond_to?(\"#{key}=\")\r\n      end\r\n    end\r\n  end\r\n\r\n  def masked_card_number\r\n    \"#{'X' * (card_number.length - 4)}#{last_four_digits}\"\r\n  end\r\n\r\n  def cancel!\r\n    self.cancelled_at = Time.now\r\n    save!\r\n  end\r\n\r\n  def save!\r\n    true\r\n  end\r\n\r\n  private\r\n\r\n  def last_four_digits\r\n    card_number[-4..-1]\r\n  end\r\nend<\/pre>\n<p>Below we have our <code>Giftcards::Repository<\/code> class, the bridge between the <code>Giftcard<\/code> class and the different adapter classes.<\/p>\n<pre class=\" brush:php\">module Giftcards\r\n  class Repository\r\n    attr_reader :adapter\r\n\r\n    def initialize(adapter)\r\n      @adapter = adapter\r\n    end\r\n\r\n    def create(amount_cents, currency)\r\n      details = adapter.create(amount_cents, currency)\r\n      Giftcard.create!({\r\n        card_number: details[:card_number],\r\n        pin: details[:pin],\r\n        currency: currency,\r\n        issuer: adapter::NAME\r\n      })\r\n    end\r\n\r\n    def balance(giftcard)\r\n      adapter.balance(giftcard.card_number)\r\n    end\r\n\r\n    def adjust(giftcard, amount_cents)\r\n      adapter.adjust(giftcard.card_number, amount_cents)\r\n    end\r\n\r\n    def cancel(giftcard)\r\n      amount_cents = balance(giftcard)\r\n      adjust(giftcard, -amount_cents)\r\n      giftcard.cancel!\r\n      giftcard\r\n    end\r\n  end\r\nend<\/pre>\n<p>Next are the adapters, which aren\u2019t fully fleshed out yet, but for the purposes of this example they\u2019ll do fine. Their interface is locked down, and they can be implemented and tested individually at a later time.<\/p>\n<p>This is where all the nasty SOAP calls would go (if you\u2019ve worked with real gift card issuers, you\u2019ll know what I\u2019m talking about), or if you\u2019re lucky, a JSON API (highly doubtful).<\/p>\n<pre class=\" brush:php\">module Giftcards\r\n  module Adapters\r\n    class BaseAdapter\r\n      # To be implemented\r\n    end\r\n\r\n    class Cardex &lt; BaseAdapter\r\n      # To be implemented\r\n    end\r\n\r\n    class Test &lt; BaseAdapter\r\n\r\n      NAME = 'test'.freeze\r\n\r\n      def create(amount_cents, currency)\r\n        pool = (0..9).to_a\r\n\r\n        {\r\n          card_number: (0..11).map{ |n| pool.sample }.join,\r\n          pin: (0..4).map{ |n| pool.sample }.join,\r\n          currency: currency\r\n        }\r\n      end\r\n\r\n      def balance(card_number)\r\n        100\r\n      end\r\n\r\n      def adjust(card_number, amount_cents)\r\n        balance(card_number) + amount_cents\r\n      end\r\n\r\n      def cancel(giftcard)\r\n        true\r\n      end\r\n    end\r\n  end\r\nend<\/pre>\n<h2>Isolating Dependencies<\/h2>\n<p>Isolating these dependencies can either be accomplished by using dependency injection, whereby you inject stub dependencies (an API wrapper which is specifically for testing and returns you a canned response immediately), or by using some form of test double or method mocking\/stubbing.<\/p>\n<h3>Using doubles<\/h3>\n<p>Doubles are a sort of \u201cfake\u201d version of dependent objects. They are most of the time incomplete representations, which only expose the methods necessary for performing the test. Rspec comes with a great library called <a href=\"https:\/\/github.com\/rspec\/rspec-mocks\">rspec-mock<\/a> which includes all sorts of different ways to produce these doubles.<\/p>\n<p>One example, which I\u2019ll use below, is to create a fake instance of the <code>Giftcard<\/code> class that only has the <code>card_number<\/code> method (and the value it returns).<\/p>\n<pre class=\" brush:php\">instance_double('Giftcard', card_number: 12345)<\/pre>\n<h3>Mocking HTTP requests<\/h3>\n<p>There are a number of ways to mock HTTP requests, and we won\u2019t dive into them here. In an article I wrote about <a href=\"http:\/\/blog.codeship.com\/architecting-rails-apps-as-microservices\/\">micro-services in Rails<\/a>, there\u2019s a pretty good example on mocking an HTTP request using the <code>Faraday<\/code> gem.<\/p>\n<p>Other ways to mock HTTP requests might involve using the <a href=\"https:\/\/github.com\/bblimke\/webmock\">webmock<\/a> gem. Or you can use <a href=\"https:\/\/github.com\/vcr\/vcr\">VCR<\/a>, which makes a real request once, records the response, and then uses the recorded response from then on.<\/p>\n<h3>Stubbing methods<\/h3>\n<p>Because of the way Ruby is written, we can actually replace an object\u2019s method with a fake version. This is done in rspec with the following code:<\/p>\n<pre class=\" brush:php\">allow(adapter).to receive(:adjust) { 50 }<\/pre>\n<p>Now when <code>adapter.adjust<\/code> is called, it will return the value <code>50<\/code> no matter what, instead of performing the expensive SOAP call to the real service. The complete test looks as follows:<\/p>\n<pre class=\" brush:php\">describe Giftcards::Repository do\r\n  describe '#adjust' do\r\n    let(:adapter)    { Giftcards::Adapters::Cardex.new }\r\n    let(:repository) { Giftcards::Repository.new(adapter) }\r\n    let(:giftcard)   do\r\n      Giftcard.new do |giftcard|\r\n        giftcard.card_number = '12345'\r\n      end\r\n    end\r\n\r\n    it 'returns new balance' do\r\n      allow(adapter).to receive(:adjust) { 50 }\r\n      expect(repository.adjust(giftcard, -50)).to eq(50)\r\n    end\r\n  end\r\nend<\/pre>\n<h3>Dependency injection<\/h3>\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Dependency_injection\">Dependency injection<\/a> is where you pass an object\u2019s dependencies to it. In this case, instead of the <code>Giftcards::Repository<\/code> class deciding which adapter it will use, we can actually explicitly pass the adapter to it, putting more control in the caller\u2019s hands.<\/p>\n<p>This technique helps us with testing, because we can replace the real object with one specifically created for testing.<\/p>\n<pre class=\" brush:php\">adapter = Giftcards::Adapters::Test.new\r\nrepository = Giftcards::Repository.new(adapter)<\/pre>\n<h2>Verifying Our Code Works as Expected<\/h2>\n<p>The real reason we write tests is so that we can be confident that our code works as expected. Dealing with dependencies is nice, but if it doesn\u2019t help us verify that our code works, it\u2019s rather pointless.<\/p>\n<h3>Testing return value<\/h3>\n<p>The simplest form of unit testing is to verify that our function returns the correct value when it is called. There are no side effects here\u2026 we simply call it and expect a result to come back.<\/p>\n<pre class=\" brush:php\">describe Giftcard do\r\n  describe '#masked_card_number' do\r\n    it 'masks number correctly' do\r\n      giftcard = Giftcard.new\r\n      giftcard.card_number = '123456780012'\r\n      expect(giftcard.masked_card_number).to eq('XXXXXXXX0012')\r\n    end\r\n  end\r\nend<\/pre>\n<h3>Testing other method called correctly<\/h3>\n<p>There are cases when the purpose of the method is to dispatch some sort of work to another method. Or in other words, it calls a method. Let\u2019s write a test to verify that this other method was called correctly. Rspec actually has a mechanism for finding this out, where we can check to make sure that an object received a certain method call with specific arguments.<\/p>\n<pre class=\" brush:php\">describe Giftcards::Repository do\r\n  describe '#balance' do\r\n    let(:adapter)    { Giftcards::Adapters::Test.new }\r\n    let(:repository) { Giftcards::Repository.new(adapter) }\r\n    let(:giftcard)   { instance_double('Giftcard', card_number: 12345) }\r\n\r\n    it 'returns balance for giftcard' do\r\n      expect(repository.balance(giftcard)).to eq(100)\r\n    end\r\n\r\n    it 'calls the balance of adapter' do\r\n      expect(repository.adapter).to receive(:balance).with(giftcard.card_number)\r\n      repository.balance(giftcard)\r\n    end\r\n  end\r\nend<\/pre>\n<h3>Testing side effects<\/h3>\n<p>Lastly, our method may produce some side effects. These could be anything from changing the state of an object (an instance variable\u2019s value) to writing to the database or a file. The important thing here is to check both the before state and the after state, so that you can be sure the side effect happened.<\/p>\n<pre class=\" brush:php\">describe Giftcard do\r\n  describe '#cancel!' do\r\n    it 'updates cancelled_at field to current time' do\r\n      giftcard = Giftcard.new\r\n      expect(giftcard.cancelled_at).to eq(nil)\r\n      giftcard.cancel!\r\n      expect(giftcard.cancelled_at).to be_a(Time)\r\n    end\r\n  end\r\nend<\/pre>\n<h3>Single responsibility<\/h3>\n<p>If your method doesn\u2019t fall into one of the three categories above \u2014 meaning that its purpose isn\u2019t defined by a result, a method call, or a side effect \u2014 perhaps it\u2019s doing too much. In that case, it should be broken down further into a series of single purpose methods.<\/p>\n<p>By following the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Single_responsibility_principle\">single responsibility principle<\/a>, your code will be much easier to test.<\/p>\n<h2>Conclusion<\/h2>\n<p>We\u2019ve covered a number of different ways to isolate dependencies in our code while writing unit tests, as well as how to verify that the method does what it\u2019s supposed to do. The most important part of testing is to actually do it. I saw on Twitter recently a Beyonce-inspired quote which seems appropriate now:<\/p>\n<p>If you love your code, put a test on it.<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"http:\/\/blog.codeship.com\/unit-testing-in-ruby\/\">Unit Testing in Ruby<\/a> from our <a href=\"http:\/\/www.webcodegeeks.com\/join-us\/wcg\/\">WCG partner<\/a>\u00a0Florian Motlik at the <a href=\"http:\/\/blog.codeship.com\/\">Codeship Blog<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In his article on Unit Testing, Martin Fowler mentions that what a unit actually is can change depending on what school of thought you come from. Many from the object-oriented world consider the Class as the unit, whereas those in the functional programming world consider the Function the unit. Even though Ruby is an object-oriented &hellip;<\/p>\n","protected":false},"author":113,"featured_media":4128,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21],"tags":[121],"class_list":["post-9604","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ruby","tag-testing"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Unit Testing in Ruby - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"In his article on Unit Testing, Martin Fowler mentions that what a unit actually is can change depending on what school of thought you come from. Many\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Unit Testing in Ruby - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"In his article on Unit Testing, Martin Fowler mentions that what a unit actually is can change depending on what school of thought you come from. Many\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2015-12-25T14:11:33+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Leigh Halliday\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@leighchalliday\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Leigh Halliday\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/\"},\"author\":{\"name\":\"Leigh Halliday\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/e496b17f78cdca27723b8e225dc6ab6b\"},\"headline\":\"Unit Testing in Ruby\",\"datePublished\":\"2015-12-25T14:11:33+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/\"},\"wordCount\":1457,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg\",\"keywords\":[\"Testing\"],\"articleSection\":[\"Ruby\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/\",\"name\":\"Unit Testing in Ruby - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg\",\"datePublished\":\"2015-12-25T14:11:33+00:00\",\"description\":\"In his article on Unit Testing, Martin Fowler mentions that what a unit actually is can change depending on what school of thought you come from. Many\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ruby\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/ruby\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Unit Testing in Ruby\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/e496b17f78cdca27723b8e225dc6ab6b\",\"name\":\"Leigh Halliday\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/bd40251a1acc424c292c35a3485264a801efa20efa7063c3e320a0a354ddafac?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/bd40251a1acc424c292c35a3485264a801efa20efa7063c3e320a0a354ddafac?s=96&d=mm&r=g\",\"caption\":\"Leigh Halliday\"},\"description\":\"Leigh is a developer at theScore. He writes about Ruby, Rails, and software development on his personal site.\",\"sameAs\":[\"http:\/\/www.leighhalliday.com\/\",\"https:\/\/x.com\/leighchalliday\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/leigh-halliday\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Unit Testing in Ruby - Web Code Geeks - 2026","description":"In his article on Unit Testing, Martin Fowler mentions that what a unit actually is can change depending on what school of thought you come from. Many","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/","og_locale":"en_US","og_type":"article","og_title":"Unit Testing in Ruby - Web Code Geeks - 2026","og_description":"In his article on Unit Testing, Martin Fowler mentions that what a unit actually is can change depending on what school of thought you come from. Many","og_url":"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2015-12-25T14:11:33+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg","type":"image\/jpeg"}],"author":"Leigh Halliday","twitter_card":"summary_large_image","twitter_creator":"@leighchalliday","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Leigh Halliday","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/"},"author":{"name":"Leigh Halliday","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/e496b17f78cdca27723b8e225dc6ab6b"},"headline":"Unit Testing in Ruby","datePublished":"2015-12-25T14:11:33+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/"},"wordCount":1457,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg","keywords":["Testing"],"articleSection":["Ruby"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/","url":"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/","name":"Unit Testing in Ruby - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#primaryimage"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg","datePublished":"2015-12-25T14:11:33+00:00","description":"In his article on Unit Testing, Martin Fowler mentions that what a unit actually is can change depending on what school of thought you come from. Many","breadcrumb":{"@id":"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/04\/ruby-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.webcodegeeks.com\/ruby\/unit-testing-ruby\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Ruby","item":"https:\/\/www.webcodegeeks.com\/category\/ruby\/"},{"@type":"ListItem","position":3,"name":"Unit Testing in Ruby"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/e496b17f78cdca27723b8e225dc6ab6b","name":"Leigh Halliday","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/bd40251a1acc424c292c35a3485264a801efa20efa7063c3e320a0a354ddafac?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bd40251a1acc424c292c35a3485264a801efa20efa7063c3e320a0a354ddafac?s=96&d=mm&r=g","caption":"Leigh Halliday"},"description":"Leigh is a developer at theScore. He writes about Ruby, Rails, and software development on his personal site.","sameAs":["http:\/\/www.leighhalliday.com\/","https:\/\/x.com\/leighchalliday"],"url":"https:\/\/www.webcodegeeks.com\/author\/leigh-halliday\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/9604","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/113"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=9604"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/9604\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/4128"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=9604"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=9604"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=9604"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}