• Stars
    star
    228
  • Rank 174,504 (Top 4 %)
  • Language
    Ruby
  • License
    MIT License
  • Created about 13 years ago
  • Updated 12 days ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Approval Tests for Ruby

Approvals

BuildGem Version Code Climate Gemnasium

Contents

Approvals are based on the idea of the golden master.

You take a snapshot of an object, and then compare all future versions of the object to the snapshot.

Big hat tip to Llewellyn Falco who developed the approvals concept, as well as the original approvals libraries (.NET, Java, Ruby, PHP, probably others).

See ApprovalTests for videos and additional documentation about the general concept.

Also, check out Herding Code's podcast #117 in which Llewellyn Falco is interviewed about approvals.

Getting Started

New Projects

The easiest way to get started with a new project is to clone the Starter Project

Configuration

Approvals.configure do |config|
  config.approvals_path = 'output/dir/'
end

snippet source | anchor

The default location for the output files is

approvals/

Usage

Approvals.verify(your_subject, :format => :json)

This will raise an ApprovalError in the case of a failure.

The first time the approval is run, a file will be created with the contents of the subject of your approval:

the_name_of_the_approval.received.txt # or .json, .html, .xml as appropriate

Since you have not yet approved anything, the *.approved file does not exist, and the comparison will fail.

Customizing formatted output

The default writer uses the :to_s method on the subject to generate the output for the received file. For custom complex objects you will need to provide a custom writer to get helpful output, rather than the default:

#<Object:0x0000010105ea40> # or whatever the object id is

Create a custom writer class somewhere accessible to your test:

class MyCustomWriter < Approvals::Writers::TextWriter
  def format(data)
    # Custom data formatting here
  end

  def filter(data)
    # Custom data filtering here
  end
end

In your test, use a string to reference your custom class:

it "verifies a complex object" do
  Approvals.verify hello, :format => "MyCustomWriter"
end

Define and use different custom writers as needed!

CLI

The gem comes with a command-line tool that makes it easier to manage the *.received.* and *.approved.* files.

The basic usage is:

approvals verify

This goes through each approval failure in turn showing you the diff.

The option --diff or -d configures which difftool to use (for example opendiff, vimdiff, etc). The default value is diff.

The option --ask or -a, which after showing you a diff will offer to approve the received file (move it from *.received.* to *.approved.*.). The default is true. If you set this to false, then nothing happens beyond showing you the diff, and you will need to rename files manually.

Workflow Using VimDiff

I have the following mapped to <leader>v in my .vimrc file:

map <leader>v :!approvals verify -d vimdiff -a<cr>

I tend to run my tests from within vim with an on-the-fly mapping:

:map Q :wa <Bar> :!ruby path/to/test_file.rb<cr>

When I get one or more approval failures, I hit <leader>v. This gives me the vimdiff.

When I've inspected the result, I hit :qa which closes both sides of the diff.

Then I'm asked if I want to approve the received file [yN]. If there are multiple diffs, this handles each failure in turn.

RSpec

For the moment the only direct integration is with RSpec.

require 'approvals/rspec'

The default directory for output files when using RSpec is

spec/fixtures/approvals/

You can override this:

RSpec.configure do |config|
  config.approvals_path = 'some/other/path'
end

The basic format of the approval is modeled after RSpec's it:

it 'works' do
  verify do
    'this is the the thing you want to verify'
  end
end

Naming

When using RSpec, the namer is set for you, using the example's full_description.

Approvals.verify(thing, :name => 'the name of your test')

Formatting

You can pass a format for your output before it gets written to the file. At the moment, only text, xml, html, and json are supported, while text is the default.

Simply add a :format => :txt, :format => :xml, :format => :html, or :format => :json option to the example:

page = '<html><head></head><body><h1>ZOMG</h1></body></html>'
Approvals.verify page, :format => :html

data = '{\'beverage\':\'coffee\'}'
Approvals.verify data, :format => :json

In RSpec, it looks like this:

verify :format => :html do
  '<html><head></head><body><h1>ZOMG</h1></body></html>'
end

verify :format => :json do
  '{\'beverage\':\'coffee\'}'
end

If you like you could also change the default format globally with:

RSpec.configure do |config|
  config.approvals_default_format = :json # or :xml, :html
end

Exclude dynamically changed values from json

Approvals.configure do |config|
  config.excluded_json_keys = {
    :id =>/(\A|_)id$/,
    :date => /_at$/
  }
end

It will replace values with placeholders:

{id: 5, created_at: "2013-08-29 13:48:08 -0700"}

=>

{id: "<id>", created_at: "<date>"}

Approving a spec

If the contents of the received file is to your liking, you can approve the file by renaming it.

For an example who's full description is My Spec:

mv my_spec.received.txt my_spec.approved.txt

When you rerun the approval, it should now pass.

Expensive computations

The Executable class allows you to perform expensive operations only when the command to execute it changes.

For example, if you have a SQL query that is very slow, you can create an executable with the actual SQL to be performed.

The first time the spec runs, it will fail, allowing you to inspect the results. If this output looks right, approve the query. The next time the spec is run, it will compare only the actual SQL.

If someone changes the query, then the comparison will fail. Both the previously approved command and the received command will be executed so that you can inspect the difference between the results of the two.

executable = Approvals::Executable.new(subject.slow_sql) do |output|
  # do something on failure
end

Approvals.verify(executable, :options => :here)

RSpec executable

There is a convenience wrapper for RSpec that looks like so:

verify do
  executable(subject.slow_sql) do |command|
     result = ActiveRecord::Base.connection.execute(command)
     # do something to display the result
  end
end

Copyright (c) 2011 Katrina Owen, released under the MIT license

More Repositories

1

ApprovalTests.Net

ApprovalTest verification library for .Net
C#
569
star
2

ApprovalTests.Java

ApprovalTest verification library for Java
Java
335
star
3

ApprovalTests.cpp

Native ApprovalTests for C++ on Linux, Mac and Windows
C++
316
star
4

ApprovalTests.Python

ApprovalTests for python
Python
146
star
5

Approvals.NodeJS

Approval Tests implementation in NodeJS
TypeScript
104
star
6

ApprovalTests.Swift

ApprovalTests for Swift, a powerful alternative to assertions
Swift
88
star
7

go-approval-tests

Go
86
star
8

ApprovalTests.Net.Json

Extends ApprovalTests to allow simple approval of complex models.
C#
27
star
9

ApprovalTests.php

PHP
25
star
10

approval_tests

Approval testing for specs and unit tests
Ruby
16
star
11

ApprovalTests.cpp.Qt

C++
15
star
12

ApprovalTests.Net.Koans

Helpful examples to learn ApprovalTests
C#
14
star
13

ApprovalTests.Dart

Approval Tests implementation in Dart
Dart
11
star
14

ApprovalTests.cpp.StarterProject

Starter project for easy learning and use of ApprovalTests.cpp
C++
11
star
15

ApprovalTests.java.Koans

Java
8
star
16

ApprovalTests.Net.Asp

Easy ways to test Asp & Aps.Mvc pages and routes
C#
8
star
17

ApprovalTests.Python.StarterProject

Starter project for getting approvaltests up and running
Python
7
star
18

ApprovalTests.Net.Wpf

Extends ApprovalTests for approval of WPF through screenshot verification.
C#
7
star
19

ApprovalTests.java.StarterProject

Sample Maven project to get started
Java
6
star
20

GroupLearningFacilitation

Printouts to help facilitate a randori/mob programming session of koans
5
star
21

ApprovalTests.js.StarterProject

Starter project to get going. Mocha/ApprovalTests
PowerShell
5
star
22

ApprovalTests.perl

ApprovalTests for Perl
Perl
5
star
23

ApprovalTests.shell

a tiny implementation of Approval Tests for the cli
Shell
5
star
24

merb_approvals

Ruby
3
star
25

ApprovalTests.Net.WinForms

Extends ApprovalTests for approval of Windows Forms through screenshot verification.
C#
3
star
26

Approvals.Net.WebApi

C#
3
star
27

ApprovalTests.cpp.Qt.StarterProject

C++
3
star
28

Approvals.Net.Excel

C#
2
star
29

ApprovalTests.Net.StatePrinter

Extends ApprovalTests to allow simple approval of complex models using StatePrinter.
C#
2
star
30

ApprovalTests.Net.StarterProject

Starter Vs2017 project with MsTest & ApprovalTests
C#
2
star
31

ApprovalTests.TypeScript.Jest.StarterProject

TypeScript
2
star
32

Approvaltests.Kotlin.StarterProject

Kotlin
2
star
33

ApprovalTests.java.StarterProject.gradle

Clone and Go
Java
2
star
34

ApprovalTests.Objective-C

ApprovalTest verification library for Objective-C
Objective-C
2
star
35

ApprovalTests.Go.StarterProject

Go
2
star
36

ApprovalTests.Net.Xunit

Simplifies xUnit support in ApprovalTests
C#
2
star
37

ApprovalTests.Net.EntityFramework

Extends ApprovalTests to allow approval of EntityFramework Queries
C#
2
star
38

ApprovalTests.plugins.intellij

IntelliJ Plugin for ApprovalTests.Java
Kotlin
2
star
39

Approvaltests.Dart.StarterProject

Starter Project for Approval Tests implementation in Dart
Dart
2
star
40

Approvaltests.Elixir

Elixir
2
star
41

ApprovalTests.cpp.StarterProject.GoogleTests

VS2017 GoogleTest starter project
C++
1
star
42

ApprovalTests.LabVIEW.StarterProject

LabVIEW
1
star
43

ApprovalTests.Dart.Flutter

Dart
1
star
44

ApprovalTests.Net.NHibernate

C#
1
star
45

PackageSettings.java

Package level settings for java
Java
1
star
46

ApprovalTests.pharo.StarterProject

Smalltalk
1
star
47

ApprovalTests.Documentation

ApprovalTests.Documentation
1
star
48

ApprovalTests.Net.NServiceBus

Adds ApprovalTests support to NServiceBus
C#
1
star
49

notes

1
star
50

ApprovalTests.cpp.StarterProject.VisualStudio

1
star
51

ApprovalTests.Scala.StarterProject

Scala
1
star
52

.github

1
star
53

EmptyFiles.Python

Python
1
star
54

ApprovalTests.Swift.StarterProject.MacOs

Swift
1
star
55

ApprovalTests.Net.Rdlc

C#
1
star
56

ApprovalTests.Groovy.StarterProject

Groovy
1
star
57

go-approval-tests-starter-project

clone and go for golang
PowerShell
1
star
58

ApprovalTests.net.StarterProject.core

C#
1
star
59

ApprovalTests.GlamorousToolkit.StarterProject

Smalltalk
1
star
60

ApprovalTests.Ruby.starterproject

Ruby
1
star
61

ApprovalTests.LabVIEW

LabVIEW
1
star
62

ApprovalTests.Net.Aspose

Extends ApprovalTests to allow approval of documents via Aspose.
C#
1
star
63

ApprovalTests.Net.AppConfig

C#
1
star
64

ApprovalTests.Angular.Jest.starterproject

TypeScript
1
star
65

ApprovalTests.lua

Approvals for lua
Lua
1
star
66

approvals.github.io

SCSS
1
star