Thursday, March 6, 2014

Stubs, Mocks, Fakes and Dummies

A “mock object”, or “mock”, is a specific kind of test double. It is an object used in a Unit Test which stands in for another object, and carries certain expectations about how what methods will be called, and how they will be called. If the expectations are not met, the test fails. By contrast, other test doubles, such as stubs objects, make no assertions about which methods will be called. The term “Mockist” refers to those programmers who use mock objects in their unit tests. There is another camp of programmers, called “Classicist” by Martin Fowler, who eschew mock objects entirely in their tests.

Dummies

  • passed around but never actually used. Usually they are just used to fill parameter lists

Fakes

  • have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example)

Stubs (classical unit testing)

  • make the SUT believe it's talking with its real collaborators
  • state verification
  • provide canned answers to calls
  • may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'
  • typically, you have to create not just the SUT but also all the collaborators that the SUT needs in response to the test
  • sometimes, alot of work goes into creating test fixtures, but they can be resused
  • cares about the final state - not how that state was derived
  • it's important to only think about what happens from the external interface and to leave all consideration of implementation until after you're done writing the test
  • stubs do not define behavior, just a return value
  • mainly useful when testing query methods that return a result and do not change the observable state of the system (are free of side effects)


Mocks (mockist/behavior driven testing)

  • make the SUT believe it's talking with its real collaborators
  • behavior verification
  • pre-programmed objects with expectations which form a specification of the calls they are expected to receive
  • typically, the SUT and mocks for its immediate collaborator objects
  • less fixture setup required, but mocks must be created every time
  • you are testing the outbound calls of the SUT to ensure it talks properly to its suppliers
  • Mockist tests are thus more coupled to the implementation of a method. Changing the nature of calls to collaborators usually cause a mockist test to break (This can be worsened by the nature of mock toolkits)
  • couples tests to implementation (changing the nature of calls to collaborators usually causes tests to break)
  • Coupling to the implementation interferes with refactoring, since implementation changes are much more likely to break tests than with classic testing
  • writing the test makes you think about the implementation of the behavior
  • must constantly think about how the SUT is going to be implemented in order to write the expectations
  • encourage behavior rich objects
  • Mocks act as a canary in coal mine: they are an early warning system that your code is beginning to depart from the path of small methods, each having a single responsibility, and each interacting with a very small set of collaborators
  • if you aren’t using tests to drive your design, there’s little point to using mock objects
  • Mock objects make more sense in an outside-in model of test-driven development
  • Mock objects enable developers to ferret out the needed interfaces of objects that don’t exist yet
  • The mocks you write while TDDing one layer of the design gives you the clues you need to work out the necessary responsibilities of the next layer down
  • mocks expect a certain method call, but define no return value
  • mainly useful when tesing command methods that change the state of a system but do not return a value


Examples

Stub Example


public interface MailService {
  public void send (Message msg);
}
public class MailServiceStub implements MailService {
  private List messages = new ArrayList();
  public void send (Message msg) {
    messages.add(msg);
  }
  public int numberSent() {
    return messages.size();
  }
}   


We can then use state verification on the stub like this.


class OrderStateTester...
  public void testOrderSendsMailIfUnfilled() {
    Order order = new Order(TALISKER, 51);
    MailServiceStub mailer = new MailServiceStub();
    order.setMailer(mailer);
    order.fill(warehouse);
    assertEquals(1, mailer.numberSent());
  }

Mock Example


class OrderInteractionTester...
  public void testOrderSendsMailIfUnfilled() {
    Order order = new Order(TALISKER, 51);
    Mock warehouse = mock(Warehouse.class);
    Mock mailer = mock(MailService.class);
    order.setMailer((MailService) mailer.proxy());

    mailer.expects(once()).method("send");
    warehouse.expects(once()).method("hasInventory")
      .withAnyArguments()
      .will(returnValue(false));

    order.fill((Warehouse) warehouse.proxy());
  }
}

Example Discussion

In both cases I'm using a test double instead of the real mail service. There is a difference in that the stub uses state verification while the mock uses behavior verification.

In order to use state verification on the stub, I need to make some extra methods on the stub to help with verification. As a result the stub implements MailService but adds extra test methods.

Mock objects always use behavior verification, a stub can go either way. The difference is in how exactly the double runs and verifies the results.

References

http://xunitpatterns.com/
http://martinfowler.com/articles/mocksArentStubs.html
http://confreaks.com/videos/659-rubyconf2011-why-you-don-t-get-mock-objects
http://devblog.avdi.org/2011/09/06/making-a-mockery-of-tdd/
http://jmock.org/oopsla2004.pdf
http://martinfowler.com/bliki/CommandQuerySeparation.html

Tuesday, March 4, 2014

Better Design Yields Awesome Fast Tests

Before all the hype of Behavior Driven Development (BDD) and Test Driven Development (TDD), I had a lot of success with the following development technique:

  1. Create Unit Test to test Application (We'll take an API based application as our example.)
  2. Implement simple API
  3. Verify Unit Test works
  4. Add more tests and build Test Suite


I called an API and asserted that the state of response based on inputs.

That was in a compiled language.

Then I started developing in Ruby, which is a dynamic language.

I learned a few things:

  • Unit Tests are more important for Ruby than Java b/c a complied language will catch interface issues early
  • Integration Tests are more important when using mocks and stubs
  • Though coding is much more enjoyable in Ruby/Rails than Java, compilation time was replaced by the time it took to run the Rails test suite


BDD Testing Didn't Make Sense

I found that every time I wrote tests for a Rails app, I had to duplicate all the objects with mocks and stubs (and the tests still took too long).

While I still don't appreciate the fact that I must use a different DSL, rspec, (which is constantly changing) to implement effective tests, I have come to accept rspec as the lingua franca of test DSLs for Rails apps.

It's just annoying to not be able to use the more recent features of rspec when working on a legacy, at this time Rails 3.x app.

Things Get Better

Eventually, I learned to not only deal with the rigorous testing requirements, but to take that pain as an incentive to design better applications.

As you find things difficult to test, you should alter your design (not your tests).

Test First Development

Here, you alter the way to test to alleviate the pain, i.e., the time it takes to run your tests.

You use Spork or Zeus to speed up your testing environment.

Without such tools, running spec_helper takes too long.

With these tools, the test environment, e.g., the Rails environment, including database connections for ActiveRecord gets loaded in the background.

Test Driven Development

With TDD, you improve the way you design your application, which in turn makes your tests run faster.

Dependency Injection

DI allows us to mock all the time consuming operations and to isolate testing to the interface of the object under test.

This typically means that we'll keep not only our controllers thin, but also our models.

We'll introduce the use of Service Objects, with flexible initializers, making it easy to swap out the persistence logic.

We'll use mocks for testing and the real thing, e.g., ActiveRecord for production.

We'll avoid using datbase operations, and isolate ourselves from 3rd party APIs.

We'll Use a Factory.build rather than a Factory.create to build in memory data relations.

Instead of running Spork or Zeus ask yourself, why does this take so long?

What is the biggest 3rd party thing I'm depending on? "Rails"

Escape from Rails Dependency

Use Ruby Mixins or Delegation.

Use Delegation when using a service is beneficial; Otherwise, use a Mixin.

Summary

Do This

  • Isolate your App from 3rd Party Frameworks and Libraries
  • Don't let controller actions talk to ActiveRecord (wrap calls to db or 3rd party libraries)
  • Use Controllers to route and pass data into something else (don't use Finders)
  • Use Cucumber (or some other integration test suite) to test for inclusion of modules
  • If its not an ActiveRecord model, then only call scopes or hand-built scopes (wrap to avoid hash construction conflicts)
  • Use Dependency Injection
  • Delegate quickly
  • Write your application in Ruby and let the Rails code call it

Get This

  • Easier Maintenance
  • Faster Tests
  • Higher Cohesion

References

http://martinfowler.com/articles/mocksArentStubs.html
http://balinterdi.com/blog/page/2/

Behavior Driven Design and Testing

Behavior Driven Design (BDD) and testing is appropriate for Object Oriented Programming (OOP).

When designing a system using OOP, focus on designing object interfaces and interactions/messages and behaviors.

Messaging

  • Design how components components communicate (more than internal behaviors)
  • The meaning of the domain model (hence behavior) of a system is found in its messages
  • Change behavior of a system by object composition, rather than modifying internal logic
  • Encapsulate implementation using "tell don't ask" coding techniques
  • Rather than procedural getting info and making decisions from that to a telling based system
  • Hide internal state (allows you to build complex APIs that you don't need to know implementation of
  • See (and test) what objects do, not what it is
  • Assert on messages going between objects
  • Well designed objects do not know who they are talking to (only need to know their collaborators' Role

Single Responsibility Principle

  • An object should only have one reason to change

OOP Testing

  • When mocking Roles, TDD becomes a Design Process
  • Mock Roles (not objects)
  • When you assert on State you are Stubbing
  • Stubs return a value (and are never the focus of the test)
  • When you assert on Messages that go between Objects, you are Mocking
  • Use Mocks for OOP, not procedural code
  • Don't mock Boundary Objects
  • Let Integration Tests or Acceptance Tests handle boundary objects
  • Mock Peers (not internals)
  • Don't Mock or Stub implementation details
  • Use Stubs to avoid hitting a real server (ex: making 3rd party api call)
  • Test response state (ex: body of response) when object becomes complex
  • Generally, think in a Tell (don't Ask) style
  • Write some Integration tests to test hitting real server (to know if they broke the interface)
  • Mock objects verify the behavior of the system under test
  • Mock objects can have expectations (Stubs can't)
  • Mock objects' expectations form the specification of the calls they are expected to receive

OOP Testing Process

  • What is not internal to my object?
  • Come up with a Scenario that demonstrates Domain Logic of expected Behavior
  • What is the role that the collaborating object needs to play?
  • What behavior should I tell the collaborating object to do?
  • Assert on the message (not the state of an object)
  • Decide, What is inside and what is outside your object?

Results

  • Decoupled/Loosely Coupled System
  • Strong Separation of Concerns
  • Tests respect code Encapsulation
  • Use Mock objects to define Interfaces
  • Ease Code Management/Changes over time
  • High level modules which define interfaces that lower level modules implement
  • "You have to implement this interface for me to use you to do this job." (Details depend on Abstractions)
  • Removal of Dependencies
  • Inversion of Control (objects created outside class in which they are used)


References

http://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627/ref=sr_1_1?ie=UTF8&qid=1393977301&sr=8-1&keywords=growing+object-oriented+software+guided+by+tests

http://jmock.org/oopsla2004.pdf

http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052

http://www.slideshare.net/paskavatta/mo-dip-15104789

Thursday, February 20, 2014

Shared Repository Model and Version Control Anti-Patterns

Shared Repository Model

The Shared Repository Model is prevalent with small teams and organizations collaborating on private projects. Everyone is granted push access to a single shared repository and topic branches are used to isolate changes.

Pull requests are used to initiate code review and general discussion about a set of changes before being merged into a mainline "master" branch.

Decide whether to use Feature Branches

If you have very few developers and you are using git as more of a source repository than a fully featured version control system, then consider committing files and merging directly to master;  Otherwise, you should probably be using feature branches.

Use Reasonable Workflow and Project Tracking Tool

When you use feature branches you should follow a reasonable workflow such as github workflow.
  • Store User Stories/Requirements in Project Tracking Tool (Jira / Pivotal Tracker / RTC)
  • Track feature stories by tasks that are assigned a ticket/tracking number
  • Reference ticket number in feature branch name
  • Developer creates feature branch, commits file changes and then submits a Pull Request
  • Other developers are notified of Pull Request, perform code review and the last one merges the feature branch to master ***
*** The last developer to perform the code review may need to perform work to merge feature branch code with master -- which can happen with other developer(s) have changed code pertaining to the feature branch between the time the feature branch was created and when the feature branch is submitted for code review via the Pull Request.

Merge

Reasons to Merge

  • When developers create feature branches
  • Multiple developers are working on same branch and you want to see each persons contributions separately
  • Clearly delineate feature branch work from merge work
  • Slightly easier to do when developers merge directly to master

Rebase

Reasons to Rebase

  • When developers merge directly to master
  • Keeps git history clean when not using feature branches (avoids "merge bubbles")

Team Development Workflow Anti Patterns

  • There are multiple developers and you are not using feature branches
  • Management is emailing spreadsheets around to track progress
  • There is no project management software in place
  • The PM software is not integrated with the version control software (github)
  • There is inconsistency with usage of PM or version control software among team members

Friday, February 14, 2014

iPad and iPhone Users Get 50 GB FREE

iPad and iPhone Users Get 50 GB FREE. Get Your #Box50GB Now!

This 50 GB promo for iOS ended in December 2011. If you have an Xperia or LG Android device, check out ouractive 50 GB promos to learn how to get free space in the cloud.
As evidenced by the overwhelming crowds during past iPhone and iPad launches, it’s clear that our lives revolve around mobile. That’s why we’re happy to announce that we’re giving away 50 GB of free storage to anyone who uses a free Box Personal account on an iOS device. That’s right, it’s 50 GB in the cloud completely free, forever. Your 50 GB of storage isn’t just limited to your mobile device – you get it anywhere you use your Box account, like on your laptop at home or your desktop at the office.
This promotion only runs for 50 days, so get your free space in the cloud by following these steps:
  1. Visit the app store and download the Box app for your iPhone, iPad or iPod touch
  2. Log in to your account or register for a new one directly from the app
  3. Start sharing and collaborating in the cloud
  4. (optional but recommended) Tell the world how you’ll use your 50 GB with the hashtag #Box50GB :)
Keep in mind you’ll need to download or update to the newest Box for iPhone and iPad app, version 2.4.3, then log into Box in order to get 50 GB. Something else cool: Your account will have an increased file size upload limit of 100MB instead of the usual 25MB!
We also updated our app with a few features that’ll make your free 50 GB even more powerful. Using AirPlay, you can now wirelessly stream Box content to an Apple TV for effortless projection of photos, videos, presentations and more. Of course, Box gets even better when you use it with others, so be sure to tell your friends, colleagues, and really, anyone with an iOS device to take advantage of this offer before it’s over.
When we originally launched our iPhone app three years ago, we suspected our users would get pretty pumped about sharing and collaborating from anywhere. In addition to the tremendous amount of interest we’ve seen with our own app, mobile adoption across the entire tech industry has been massive. For example, analysts estimate that over 100 million people will have iPads or iPhones by the end of this year; to put that figure in perspective, that’s larger than the entire population of France by a pretty huge margin – nearly 30 million.
The future of mobile is about being free of storage restrictions and closed systems. With this offer, all iOS users will see the benefit of having all of their critical information available at their fingertips, from anywhere. And if you’re already using Box, I’m sure you won’t mind getting some extra room in the cloud. Be on the lookout for tips, contests and other info about your free 50 GB over the next 50 days.
Welcome to the cloud!

OFFER ENDS 2/15/2014 SO HURRY!

References

http://blog.box.com/2011/10/were-giving-ios-users-insane-amounts-of-free-storage-box50gb/

Wednesday, February 5, 2014

Too Many Specs Failing?

Could be that you simply need to clone the structure of your development database into your test database.

Clone Your Test Database


bundle exec rake db:test:clone

Notes

  • The only specs that pass when the test database is not configured properly should be tests that don't reference the test database
  • db:test:clone is just a combination of db:schema:dump and db:test:load
  • db:test:load is the same as db:schema:load, but it runs against the test (not development) database

Run Specific Rspec Tests Under Specific Directory

You can run specific rspec tests under a specific directory by
  • specifying the directory
  • using an rspec tag option


For example, if you want to run model specs that you've tagged as work in progress (wip) do the following:

Add tag to spec


require 'spec_helper'

describe HomeController do
  render_views
  it "Logs in Person with non-blank name", :lex_tag => 'wip' do
    person = Factory(:Person, name: "non-blank name")
    get :login
    response.should redirect_to(people_path)
  end
  it "does not log in Person with blank name" do
    person = Factory(:Person, name: "") # blank name
    get :login
    response.should redirect_to(root_path)
  end
end

Run spec like so


$ be rspec --pattern spec/models/*_spec.rb --tag lex_tag:wip

In this example, we are running model specs that do not have a tag named ":lex_tag" with a value of "wip"

Summary

By specifying the directory, you limit the number of specs to run to a logical grouping.

By using rspec tags, you can be very specific about which individual tests you run.


Notes

  • You can negate a tag using the "~" character
  • To be compatible with the Cucumber syntax, tags can optionally start with a @, that will be ignored. Example: @lex_tag
  • There is nothing special about "lex_tag", you can name your tag nearly anything, but using a name allows multiple developers to annotate without confusion.
  • You would not want to check specs into your source code repository that had tag names that referenced individuals
  • You might want to use tags to group specs according to other user acceptance testing criteria or perhaps tag tests for particular server deployment environments
  • So, tags can be used to group specs, not by static folder directories but by any criteria you wish

References

https://www.relishapp.com/rspec/rspec-core/v/2-3/docs/command-line/tag-option#exclude-examples-with-a-name:value-tag