Skip to content
An Automatic Automated Test Writer
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
bin Handle single flag when generate command is not included. Dec 5, 2014
lib updates for rubocop style guide May 11, 2016
script Use script/test in TravisCI and update contributing info Nov 29, 2014
spec updates for rubocop style guide May 11, 2016
.gitignore Add bootstrap and test scripts Nov 29, 2014
.rspec Write a failing generator test Aug 9, 2014
.travis.yml Allow Ruby 2.0.0 failure May 4, 2016 Use script/test in TravisCI and update contributing info Nov 29, 2014
LICENSE Update readme file, add Aug 4, 2014 Remove Code Climate badge. Dec 12, 2017
zapata.gemspec updates for rubocop style guide May 11, 2016


Who has time to write tests? This is a revolutionary tool to make them write themselves.

Gem Version Build Status Dependency Status Coverage Status

Emiliano Zapata

What is your problem?

There comes a day where you have this bullshit class RobotToTest. We need tests. :shipit:

class RobotToTest
  def initialize(human_name, cv)
    @name = robot_name(human_name)

  def robot_name(human_name)

  def cv
    { planets: planets }

  def nested_fun_objects(fun_objects)
    'It was fun'

  def self.prefix


  def planets
    ['Mars', Human.home]

  def fun_objects
    [%i(array in array), { hash: nested_hash }]

  def nested_hash
    { in_hash: { in: array } }

  def array

# just another class to analyze
class Human
  def initialize
    human_name = 'Emiliano'

  def self.home

Solving it

You run zapata generate app/models/robot_to_test.rb and pop the champagne. Zapata generated spec/models/robot_to_test_spec.rb for you.

describe RobotToTest do
  let(:robot_to_test) do'Emiliano', { planets: ['Mars', Human.home] })

  it '#robot_name' do
    expect(robot_to_test.robot_name('Emiliano')).to eq('Robot_Emiliano')

  it '#cv' do
    expect( eq({ planets: ['Mars', 'Earth'] })

  it '#nested_fun_objects' do
      [:array, :in, :array],
        hash: {
          in_hash: {
            in: ['array']
    ])).to eq('It was fun')

  it '#prefix' do
    expect(RobotToTest.prefix).to eq('Robot')

What does it do?

It tries to write a passing RSpec spec off the bat. It does fancy analysis to predict the values it could feed to the API of a class.

To be more specific:

  • Analyzes all vars and methods definitions in app/models
  • Checks what arguments does a testable method in app/models/robot_to_test.rb need
  • Searches for such variable or method name in methods in analyzed
  • Selects the most probable value by how many times it was repeated in code
  • Runs the RSpec and fills in the expected values of the test with those returned by RSpec

For more things it can currently do check test files

Workflow with Zapata

Say you are writing some new feature on your existing project. Before writing that, you probably want to test out the current functionality. But who has time for that?

You let Zapata create that quick spec for you. Think of it as a current functionality lock. Write more code and when you're happy with the result - lock it up again.


  • Ruby 2.1+
  • Rails 3.0+

Ruby 1.9.3 and older version support is in next release and can be checked out here.


It should be as easy as

gem install zapata


gem 'zapata', groups: %w(development test)


To use run

zapata generate app/models/model_name.rb

To ignore other files and analyze a single model you want to generate a spec for:

zapata generate app/models/model_name.rb --single

Collaboration ❤️

It is encouraged by somehow managing to bring a cake to your house. I promise, I will really try.

This is a great project to understand language architecture in general. A project to let your free and expressionistic side shine through by leaving meta hacks and rainbows everywhere.

Thank you to everyone who do. I strongly believe that this can make the developer job less robotic and more creative.

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

To install, run:

cd zapata

For specs:


# or

bundle exec rspec --pattern "spec/*_spec.rb"


I am well aware that this is featured in Ruby Weekly 223. On that note I'd like to thank everybody who helped it shine through.

Special thanks to my comrade @jpalumickas, with whom we share a vision of a better world. Also - thank you @edgibbs, for being the early contributor. @morron - for caring.


Copyright (c) 2014-2018 Justas, Andrew, Ed, Dmitry, Domas. See LICENSE for details.

You can’t perform that action at this time.