= Tack

USE AT YOUR OWN RISK. Tack is a work in progress and the API will change in the future.

Tack is a {interface gem}[http://jamesarosen.com/post/783132142/on-interface-gems] for testing. No matter what test framework you use, it provides a unified API to query a test suite and run tests. Additionally, it provides a simple middleware system so anyone can write test tools that will immediately work for all supported test frameworks.

In other words, Tack is like Rack, but for testing. Tack currently supports Test::Unit, Shoulda, and RSpec.

== Who cares?

=== Ruby hackers in general

Out of the box, Tack provides a command line tool to run any type of test suite (even one that includes tests written in different frameworks). As a result, you can write tests in any framework and run them using the same tool with the same options.

Tack also supports customization via middleware, so you can customize its behavior and output to your liking.

==== Examples

Tack provides sensible behavior out of the box:

    $ tack test/foo_test.rb                                 # run a single test file
    $ tack test/foo_test.rb test/bar_test.rb                # run all tests in two test files
    $ tack test                                             # run all test files in the 'test' directory (recursive)
    $ tack -Ilib test                                       # the same as above, but load the 'lib' directory first
    $ tack -Ilib test -n 'some test'                        # run all tests whose name contains the substring 'some test'
    $ tack foo_test.rb -n 'some test' -n 'other test'       # run all tests in foo_test.rb that contain 'some test' OR 'other test'
    $ tack foo_test.rb -d                                   # display all tests, but do not run them
    $ tack foo_test.rb -v                                   # display each test name as before it is run
    $ tack foo_test.rb -u                                   # enable the debugger (just call 'debugger' to set a breakpoint)
    $ tack foo_test.rb -o                                   # display the 10 slowest tests

==== More options

    Usage: tack [options] [file]
        -I, --include PATH               Specify $LOAD_PATH (may be used more than once).
        -n, --name PATTERN               Run only tests that match pattern. Can be used multiple times to run tests that match ANY of the patterns.
        -u, --debugger                   Enable ruby-debugging.
        -o, --profile [NUMBER]           Display a text-based progress bar with profiling data on the NUMBER slowest examples (defaults to 10).
        -s, --shuffle                    Run tests in randomized order.
        -R, --reverse                    Run tests in reverse order.
        -F, --fork                       Run each test in a separate process
        -v, --verbose                    Display the full test name before running
        -d, --dry-run                    Display (but do not run) matching tests
        -b, --backtrace                  Output full backtrace
            --adapters                   Display the adapters that will be used for each file and quit.
            --middleware                 Display the middleware stack and quit.
            --no-config                  Do not load options from the .tackrc config file
        -h, --help                       Show this message

=== Test tool hackers

If you are building a test tool, it's a pain to write bindings to each test framework you want to support (and make sure it works across versions). Instead, write your app to use the Tack API and you'll support all Tack-compatible frameworks without any additional work.

Additionally, Tack's middleware system makes it easy to mix and match functionality, so your tool will play nicely with other tools.

=== Test framework hackers

If you're building a new test framework, you'll get tons of existing tools and functionality by making a Tack adapter for your library.

=== IDE hackers

Tack's unified API for displaying all tests in a suite and running them selectively makes building IDE support for many testing frameworks simple.

=== API

At a high level, Tack has tests, adapters, and middleware.

==== Tests

Each test is represented as an array of three values: <tt>[path, contexts, description]</tt>
* <tt>path</tt>: a path name (string) of the file on disk that contains the test
* <tt>contexts</tt>: an array of strings that describe each nested context
* <tt>description</tt> - the test name (string)

==== Adapters

Adapters are the classes that actually interact with the test libraries. Each one must implement:
* <tt>#run_test(file, contexts, description)</tt>: runs the provided test and returns a result
* <tt>#tests_for(file)</tt>: returns all tests for a file

==== Middleware

Middleware must include sane implementations of the following
* <tt>#run_suite(tests)</tt>
* <tt>#run_test(file, contexts, description)</tt>

Just like Rack, each Tack middleware is passed the next middleware in the chain.

=== Examples

A blog post about implementing some simple features as middleware here: http://bbrinck.com/post/850090134/test-dependency-detection-in-tack

== Upcoming features

Tack is a work in progress but many features are coming up. Help is appreciated.

* Support for Cucumber, Riot, Bacon, and more
* Rake tasks
* Documentation on the actual API

== Note on Patches/Pull Requests
 
* Fork the project.
* Make your feature addition or bug fix.
* Add tests for it. This is important so I don't break it in a
  future version unintentionally.
* Commit, do not mess with rakefile, version, or history.
  (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
* Send me a pull request. Bonus points for topic branches.

== Acknowledgements

Tack is heavily inspired by Rack and Faraday and borrows ideas and code from both. Also, initial versions of the Test::Unit and RSpec adapters borrowed code from Hydra while a lot of the formatter code was taken from RSpec.

== Copyright

Copyright (c) 2010 Ben Brinckerhoff. See LICENSE for details.
