riot-0.12.7/0000755000004100000410000000000012261222026012601 5ustar www-datawww-datariot-0.12.7/Rakefile0000644000004100000410000000135412261222026014251 0ustar www-datawww-datarequire 'bundler' Bundler::GemHelper.install_tasks task :default => ["test:all"] task "test:all" => ["test:core", "test:extensions"] require 'rake/testtask' Rake::TestTask.new("test:core") do |test| test.libs << 'test' test.pattern = 'test/core/**/*_test.rb' test.warning = true test.verbose = false end Rake::TestTask.new("test:extensions") do |test| test.libs << 'test' test.pattern = 'test/extensions/*_test.rb' test.warning = true test.verbose = false end # # Benchmarks def run_benchmarks(bin) Dir["test/benchmark/*.rb"].each do |file| puts ">> Running #{file}" puts %x[#{bin} #{file}] end end desc "Run all of them fancy benchmarks, Howard!" task("test:benchmarks") { run_benchmarks("ruby") } riot-0.12.7/CHANGELOG0000644000004100000410000002224112261222026014014 0ustar www-datawww-data# @markup markdown # 0.12.6 * Catch and report on errors that occur while running middleware. Context with error in middleware will not run. * Errors that occur during a setup, hookup, or teardown are handled gracefully * close #31 - RR seems to carry over some latent varification state between situations # 0.12.5 * Remove doc for some deprecated macros: not, exists, any [charlietanskley] * Deprecate two more macros [charlietanskley] * make riot run -w clean. None of those pesky warnings [achiu] * Use #inspect for printing arguments in error results [Mon-Ouie] * Move BlankSlate into Riot namespace [Mon-Ouie] * Setting options in a sub-context don't leak back into the parent context [skade] * Remove deprecated `not!` macro [charlietanksley] * Fix all warnings so riot runs `-w` clean # 0.12.4 * Adding Riot.plain! option for not printing output in color [c00lryguy, jaknowlden] # 0.12.3 * Going nuts with context helpers: should_not, asserts/denies_topic arguments [achiu] This works now: `should_not("do something")` as an alias for `denies` You can now pass arguments to `asserts`, `denies`, `should`, and `should_not`. ``` context "Playing with hashes" do setup do { "foo" => "bar" } end asserts(:[], "foo").equals("bar") should(:[], "foo").equals("bar") denies(:[], "foo").equals("goo") should_not(:[], "foo").equals("goo") end # Playing with hashes ``` * Exit gracefully if a child process exited with failing status [timgaleckas] No tests will run in this situation. * No status displayed if no tests run [timgaleckas] * Adding a `denies_topic` macro to Context [Mon-Ouie] # 0.12.2 * RDoc'ed the hell out of everything [jaknowlden] * Deprecating the not! assertion macro. It may just be gone by 0.13.0 [jaknowlden] * Remove ANSI-color dependency [achiu] * Switch from Jeweler to Bundler [achiu] * Add PrettyDotMatrixReporter [achiu] # 0.12.1 * Error reporting now filters the backtrace to include only meaningful line items. [mbriggs] * Added ability to pass method arguments to asserts. [sirupsen] # 0.12.0 * Negative tests are finally here! Added support for `denies` and adjusted macros to care about it with `devaluate`. [jaknowlden, achiu] ``` denies("my name") { "Rumplestiltzkin" }.equals("Henry") ``` # 0.11.4 * [skade] Passing Proc's instead of lambdas to `instance_eval` to comply with ruby 1.9.2. * [nu7hatch] Added `describe` alias for `context` for easier rspec porting. Useful at the top level and within a context. Who can argue with porting from rspec to riot? Not me. ``` describe "My thing" do asserts(:size).equals(:small) end # My thing ``` The following also works: ``` context "Another thing is" describe "my" do asserts_topic.equals("marshmallow") # this test will fail ... because it will ... because it's wrong end # my end # Another thing is ``` # 0.11.3 * [jaknowlden] Modified `matches` assertion macro to treat actual as a string before executing regular expression comparison. ``` asserts("a number") { 42 }.matches(/\d+/) # same as asserts("a number as string") { "42" }.matches(/\d+/) ``` # 0.11.2 * [jaknowlden] [ISSUE] Options were not nesting. Now fixed. # 0.11.1 * [jaknowlden] Middleware can now acts more like you would expect. Middleware now know the next neighbor in the chain and can do stuff to the context before and after the user-defined context is prepared. Removes support for the handle? method. Now we act more like a Rack app. ``` class MyMiddleware < Riot::ContextMiddleware register def call(context) context.setup { "fooberries" } middleware.call(context) context.hookup { "furberries" } if context.option(:barns) end end ``` # 0.11.0 * [jaknowlden] Added option to Context#setup which puts the specific setup block at the beginning of the setups to be called for a context. Also useful for middlewares. ``` context "Foo" do setup { puts "called second" } setup { puts "called third" } setup(true) { puts "called first" } end # Foo ``` * [jaknowlden] Added idea of options for a context. This is another feature picked up from riot-rails work. Essentially, these are useful for middlewares. For instance, if you wanted to tell a middleware that was looking for a "transactional" option before running code in a transaction block, you might do this: ``` context User do set :transactional, true end # User ``` The middleware might do something with it: ``` class TransactionalMiddleware < Riot::ContextMiddleware register def handle?(context) context.option(:transactional) == true; end def prepare(context) # transactional stuff end end # TransactionalMiddleware ``` You can call set as many times as you like ``` context User do set :transactional, true set :foo, :bar end ``` * [jaknowlden] ContextMiddleware: a construction pattern that allows for custom code to be applied to any context given that the middleware chooses to. This is something I started building into riot-rails and decided it was useful enough to just put it into riot itself. If, for instance, you wanted to add a setup with some stuff only if the context description was equal to "Your Mom": ``` class YourMomMiddleware < Riot::ContextMiddleware register def handle?(context) context.description == "Your Mom" end def prepare(context) context.setup do "your mom is the topic" end end end # YourMomMiddleware ``` # 0.10.13 * [jaknowlden] Helpers are now run with other setups, not separately. Which means you could use a helper in a setup. ``` context "Foo" do helper(:user) { User.new } setup do Baz.new(:user => user) # :) end end # Foo ``` * [vandrijevik] Correctly report non-RR assertion failures and errors when RR is used. ``` context "Foo.bar" do asserts("baz is called") do mock(Foo).baz raise RuntimeError.new("oh noes") end end ``` would previously return [:fail, "baz() Called 0 times. Expected 1 times."], and will now correctly return [:error, #] * [jaknowlden] Recording description as is. Providing #detailed_description for proper behavior ``` foo_context = context(Foo) {} bar_context = foo_context.context(Bar) {} bar_context.description => Bar bar_context.detailed_description => "Foo Bar" ``` * [jaknowlden] No longer assuming topic when no block provided to an assertion. Instead, assuming block fails by default. Use `asserts_topic` only now. ``` context "foo" do setup { "bar" } asserts_topic.kind_of(String) asserts("topic").kind_of(String) # Will fail since block returns `false` asserts("topic").equals(false) # Will actually pass :) end ``` # 0.10.12 * [vandrijevik] Recognizing file and line number of an assertion declaration on failure * [vandrijevik,jaknowlden] RR support in Riot ``` # teststrap.rb require 'riot' require 'riot/rr' # your-test.rb context "foo" do asserts("failure due to not calling hello") { mock!.hello {"world"} } # actually fails end ``` * [jaknowlden] Added Riot::Message to make messages in macros easier to write ``` def evaluate(actual, expected) # ... expected == actual pass(new_message.received(expected)) ? fail(expected(expected).not(actual)) # ... end ``` * [jaknowlden] Added responds_to as a respond_to alias * [jaknowlden] Added the equivalent_to macro to compare case equality (===). equals is now (==) * [jaknowlden] Assuming RootContext if nil parent provided. Added Context#parent to the API ``` Riot::Context.new("Hi", nil) {}.parent.class => Riot::RootContext ``` # 0.10.11 * [gabrielg, jaknowlden] Context#asserts_topic now takes an optional description ``` asserts_topic.exists asserts_topic("some kind of description").exists ``` * [gabrielg, jaknowlden] Added not! assertion macro ``` setup { User.new(:funny? => false) } asserts(:funny?).not! ``` * [jaknowlden] Added Context#hookup to add some setup code to an already defined topic ``` context "yo mama" do setup { YoMama.new } # ... context "is cool" do hookup { topic.do_something_involving_state } asserts_topic.kind_of?(YoMama) end end ``` * [jaknowlden] Added Riot.alone! mode to ensure Riot.run is not run at-exit ``` Riot.alone! Riot.run ``` This will still print output unless you also Riot.silently! * [gabrielg, jaknowlden] Returning non-zero status at-exit when tests don't pass # 0.10.10 * [dasch, jaknowlden] Passing assertion macros can now return a custom message ``` def evaluate(actual, *expectings) 1 == 1 ? pass("1 does equal 1") : fail("1 does not equal 1 in this universe") end ``` * [jaknowlden] Removing Context#extend_assertions and related code * [dasch] Allow the use of symbolic descriptions as shorthands for sending the message to the topic ``` setup { "foo" } asserts(:upcase).equals("FOO") ``` * [jaknowlden, splattael] Added AssertionMacro and #register for macros ``` module My class CustomThingAssertion < Riot::AssertionMacro register :custom_thing expects_exception! def evaluate(actual, *expectings) # ... end end Riot::Assertion.register_macro :custom_thing, CustomThingAssertion end ``` * [splattael] Replace IOReporter#say with #puts. Also add #print. ``` class SomeNewReporter < IOReporter def pass puts "I PASSED" end def fail print "F" end # ... end ``` # 0.10.9 and before See the commit log: http://github.com/thumblemonks/riot/commits/master riot-0.12.7/riot.gemspec0000644000004100000410000000152312261222026015124 0ustar www-datawww-data# -*- encoding: utf-8 -*- $:.unshift(File.expand_path("../lib", __FILE__)) require "riot/version" Gem::Specification.new do |s| s.name = %q{riot} s.version = Riot::VERSION s.platform = Gem::Platform::RUBY s.authors = ["Justin 'Gus' Knowlden"] s.summary = %q{An extremely fast, expressive, and context-driven unit-testing framework. Protest the slow test.} s.description = %q{An extremely fast, expressive, and context-driven unit-testing framework. A replacement for all other testing frameworks. Protest the slow test.} s.email = %q{gus@gusg.us} s.files = `git ls-files`.split("\n") s.homepage = %q{http://github.com/thumblemonks/riot} s.require_paths = ["lib"] s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.add_dependency 'rr', '>=0' end riot-0.12.7/Gemfile0000644000004100000410000000012412261222026014071 0ustar www-datawww-datasource "http://rubygems.org" gemspec group "test" do gem "rake", ">=0.8.7" end riot-0.12.7/MIT-LICENSE0000644000004100000410000000206212261222026014235 0ustar www-datawww-dataCopyright (c) 2008 Justin Knowlden, Thumble Monks Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. riot-0.12.7/.travis.yml0000644000004100000410000000022112261222026014705 0ustar www-datawww-datalanguage: ruby before_install: - gem update --system - gem --version bundler_args: --without development rvm: - 1.8.7 - 1.9.2 - 1.9.3 riot-0.12.7/lib/0000755000004100000410000000000012261222026013347 5ustar www-datawww-datariot-0.12.7/lib/riot/0000755000004100000410000000000012261222026014324 5ustar www-datawww-datariot-0.12.7/lib/riot/assertion_macro.rb0000644000004100000410000001153612261222026020047 0ustar www-datawww-datarequire 'riot/message' module Riot # The base class for all assertion macros. # # == Using macros # # Macros are applied to the return value of assertions. For example, the # +empty+ macro asserts that the value is empty or denies that it is empty e.g. # # asserts(:comments).empty? # denies(:comments).empty? # # == Writing your own macros # # Macros are added by subclassing {AssertionMacro}. For example, here's # the implementation of +empty+: # # class EmptyMacro < AssertionMacro # register :empty # # def evaluate(actual) # actual.length == 0 ? pass : fail(expected_message(actual).to_be_empty) # end # # def devaluate(actual) # actual.empty? ? fail(expected_message(actual).to_not_be_empty) : pass(new_message.is_empty) # end # end # class AssertionMacro class << self # Whether the macro expects an exception to be thrown. # # @return [Boolean] attr_reader :expects_exception # @private # The default macro. # # @return [Riot::AssertionMacro] def default @default_macro ||= new end # Specify that the macro expects an exception to be thrown by the assertion. def expects_exception! @expects_exception = true end # Register the macro under the given name. # # @param [String, Symbol] name the name of the macro def register(name) Assertion.register_macro name, self end end # During failure reporting, what line number did the failure occur at # @return [Number] attr_accessor :line # During failure reporting, what file did the failure occur in # @return [String] attr_accessor :file # Returns a status tuple indicating the assertion passed. # # @param [String] message the message to report with # @return [Array[Symbol, String]] def pass(message=nil) [:pass, message.to_s]; end # Returns a status tuple indicating the assertion failed and where it failed it if that can be # determined. # # @param [String] message the message to report with # @return [Array[Symbol, String, Number, String]] def fail(message) [:fail, message.to_s, line, file]; end # Returns a status tuple indicating the assertion had an unexpected error. # # @param [Exception] ex the Exception that was captured # @return [Array[Symbol, Exception]] def error(ex) [:error, ex]; end # Returns +true+ if this macro expects to handle Exceptions during evaluation. # # @return [boolean] def expects_exception?; self.class.expects_exception; end # Supports positive assertion testing. This is where magic happens. # # @param [Object] actual the value returned from evaling the {Riot::Assertion Assertion} block # @return [Array] response from either {#pass}, {#fail} or {#error} def evaluate(actual) actual ? pass : fail("Expected non-false but got #{actual.inspect} instead") end # Supports negative/converse assertion testing. This is also where magic happens. # # @param [Object] actual the value returned from evaling the {Riot::Assertion Assertion} block # @return [Array] response from either {#pass}, {#fail} or {#error} def devaluate(actual) !actual ? pass : fail("Expected non-true but got #{actual.inspect} instead") end # Creates a new message for use in any macro response that is initially empty. # # @param [Array] *phrases array of object whose values will be inspected and added to message # @return [Riot::Message] def new_message(*phrases) Message.new(*phrases); end # Creates a new message for use in any macro response that will start as "should have ". # # @param [Array] *phrases array of object whose values will be inspected and added to message # @return [Riot::Message] def should_have_message(*phrases) new_message.should_have(*phrases); end # Creates a new message for use in any macro response that will start as "expected ". # # @param [Array] *phrases array of object whose values will be inspected and added to message # @return [Riot::Message] def expected_message(*phrases) new_message.expected(*phrases); end end end require 'riot/assertion_macros/any' require 'riot/assertion_macros/assigns' require 'riot/assertion_macros/empty' require 'riot/assertion_macros/equals' require 'riot/assertion_macros/equivalent_to' require 'riot/assertion_macros/exists' require 'riot/assertion_macros/includes' require 'riot/assertion_macros/kind_of' require 'riot/assertion_macros/matches' require 'riot/assertion_macros/nil' require 'riot/assertion_macros/raises' require 'riot/assertion_macros/raises_kind_of' require 'riot/assertion_macros/respond_to' require 'riot/assertion_macros/same_elements' require 'riot/assertion_macros/size' riot-0.12.7/lib/riot/situation.rb0000644000004100000410000000470512261222026016676 0ustar www-datawww-datamodule Riot # A {Riot::Situation} is virtually a stack frame for a single context run. The intent is for all blocks to # be evaluated against an instance of a Situation. Given the following superfluous context: # # context "Foo" do # block-1 # # setup do # block-2 # {:bar => "baz"} # end # # asserts "its hash" do # block-3 # topic # end.equals do # block-4 # {:bar => "baz"} # end # # end # Foo # # In this example, block-1 will be evaluated against a {Riot::Context} instance. Whereas block-2, block-3, # and block-4 will all be evaluated against the same Situation instance. Situation instances (situations) # are bound to a single context run; they are not shared across context runs, regardless of their position # in the test tree structure. # # What is gained from doing it this way is: # * variables, methods, etc. set in one situation do not contaminate any others # * variables, methods, etc. defined during a context run do not stick with the context itself # * which means that testing state is independent of the test definitions themselves class Situation # Returns the currrently tracked value of +topic+ # # @return [Object] whatever the topic is currently set to def topic @_topic ||= nil end # This is where a setup block is actually evaluated and the +topic+ tracked. # # @param [lambda] &block a setup block # @return [Object] the current topic value def setup(&block) @_topic = self.instance_eval(&block) end # This is where a defined helper is born. A method is defined against the current instance of +self+. # This method will not be defined on any other instances of Situation created afterwards. # # @param [Symbol, String] name the name of the helper being defined # @param [lambda] &block the code to execute whennever the helper is called def helper(name, &block) (class << self; self; end).send(:define_method, name, &block) end # Anonymously evaluates any block given to it against the current instance of +self+. This is how # {Riot::Assertion assertion} and {Riot::AssertionMacro assertion macro} blocks are evaluated, # for instance. # # @param [lambda] &block the block to evaluate against +self+ # @return [Object] whatever the block would have returned def evaluate(&block) self.instance_eval(&block) end end # Situation end # Riot riot-0.12.7/lib/riot/context.rb0000644000004100000410000001327112261222026016341 0ustar www-datawww-datarequire 'riot/context_options' require 'riot/context_helpers' module Riot RootContext = Struct.new(:setups, :teardowns, :detailed_description, :option_set) # Defines the classes {Riot::Context} will use when creating new assertions and situations. module ContextClassOverrides # Returns the default class used for generating new {Riot::Assertion Assertion} instances. Defaults to # {Riot::Assertion}. # # @return [Class] def assertion_class; Assertion; end # Returns the default class used for generating new {Riot::Situation Situation} instances. Defaults to # {Riot::Situation}. # # @return [Class] def situation_class; Situation; end end # ContextClassOverrides # An {Riot::Assertion} is declared within a Context. The context stores setup and teardown # blocks, and allows for nesting and refactoring. Extension developers may also configure # {Riot::ContextMiddleware Middleware} objects in order to extend the functionality of a Context. class Context include ContextClassOverrides include ContextOptions include ContextHelpers # The set of middleware helpers configured for the current test space. # # @return [Array] def self.middlewares; @middlewares ||= []; end # The partial description of just this context. # # @return [String] attr_reader :description # The parent context. # # @return [Riot::Context, nil] a context or nil attr_reader :parent # Creates a new Context # # @param [String] description a partial description of this context # @param [Riot::Context, nil] parent a parent context or nothing # @param [lambda] definition the body of this context def initialize(description, parent=nil, &definition) @parent = parent || RootContext.new([],[], "", {}) @description = description @contexts, @setups, @assertions, @teardowns = [], [], [], [] @context_error = nil @options = @parent.option_set.dup prepare_middleware(&definition) rescue Exception => e @context_error = e end # Create a new test context. # # @param [String] description # @return [Riot::Context] the newly created context def context(description, &definition) new_context(description, self.class, &definition) end alias_method :describe, :context # @private # Returns an ordered list of the setup blocks for the context. # # @return [Array] def setups @parent.setups + @setups end # @private # Returns an ordered list of the teardown blocks for the context. # # @return [Array] def teardowns @parent.teardowns + @teardowns end # Executes the setups, hookups, assertions, and teardowns and passes results on to a given # {Riot::Reporter Reporter}. Sub-contexts will also be executed and provided the given reporter. A new # {Riot::Situation Situation} will be created from the specified {#situation_class Situation class}. # # @param [Riot::Reporter] reporter the reporter to report results to # @return [Riot::Reporter] the given reporter def run(reporter) reporter.describe_context(self) unless @assertions.empty? if @context_error reporter.report("context preparation", [:context_error, @context_error]) else local_run(reporter, situation_class.new) run_sub_contexts(reporter) end reporter end # @private # Used mostly for testing purposes; this method does the actual running of just this context. # @param [Riot::Reporter] reporter the reporter to report results to # @param [Riot::Situation] situation the situation to use for executing the context. def local_run(reporter, situation) runnables.each do |runnable| code, response = *runnable.run(situation) reporter.report(runnable.to_s, [code, response]) break if code == :setup_error end end # Prints the full description from the context tree, grabbing the description from the parent and # appending the description given to this context. # # @return [String] the full description for this context def detailed_description "#{parent.detailed_description} #{description}".strip end private # Iterative over the registered middlewares and let them configure this context instance if they so # choose. {Riot::AllImportantMiddleware} will always be the last in the chain. def prepare_middleware(&context_definition) last_middleware = AllImportantMiddleware.new(&context_definition) Context.middlewares.inject(last_middleware) do |previous_middleware, middleware| middleware.new(previous_middleware) end.call(self) end # The collection of things that are {Riot::RunnableBlock} instances in this context. # # @return [Array] def runnables setups + @assertions + teardowns end # Execute each sub context. # # @param [Riot::Reporter] reporter the reporter instance to use # @return [nil] def run_sub_contexts(reporter) @contexts.each { |ctx| ctx.run(reporter) } end # Creates a new context instance and appends it to the set of immediate children sub-contexts. # # @param [String] description a partial description # @param [Class] klass the context class that a sub-context will be generated from # @param [lambda] definition the body of the sub-context # @return [#run] something that hopefully responds to run and is context-like def new_context(description, klass, &definition) (@contexts << klass.new(description, self, &definition)).last end end # Context end # Riot riot-0.12.7/lib/riot/assertion.rb0000644000004100000410000000662212261222026016666 0ustar www-datawww-datamodule Riot # An Assertion is the engine behind evaluating a single test that can be reported on. When +asserts+ # or +denies+ is used, the description and assertion block are used to generate a single Assertion # instance. When running an Assertion, a [Riot::Situation] instance is required for data scoping. The # result of calling run will be a status tuple that can be used for reporting. # # In general, you won't be spending much time in here. class Assertion < RunnableBlock class << self # Returns the list of assertion macros that have been successfully registered # # @return [Hash] def macros; @@macros ||= {}; end # Registers a [Riot::AssertionMacro] class to a given +name+. Name is distinct, which means any future # registrations for the same name will replace previous ones. +name+ will always be converted to a # string first. # # @param [String, Symbol] name The handle the macro will be associated with # @param [Class] assertion_macro A [Riot::AssertionMacro] class def register_macro(name, assertion_macro) macros[name.to_s] = assertion_macro end end # Setups a new Assertion. By default, the assertion will be a "positive" one, which means +evaluate+ will # be call on the associated assertion macro. If +negative+ is true, +devaluate+ will be called instead. # Not providing a definition block is just kind of silly since it's used to generate the +actual+ value # for evaluation by a macro. # # @param [String] definition A small description of what this assertion is testing # @param [Boolean] negative Determines whether this is a positive or negative assertion # @param [lambda] definition The block that will return the +actual+ value when eval'ed def initialize(description, negative=false, &definition) super(description, &definition) @negative = negative @expectings, @expectation_block = [], nil @macro = AssertionMacro.default end # Given a {Riot::Situation}, execute the assertion definition provided to this Assertion, hand off to an # assertion macro for evaluation, and then return a status tuple. If the macro to be used expects any # exception, catch the exception and send to the macro; else just return it back. # # Currently supporting 3 evaluation states: :pass, :fail, and :error # # @param [Riot::Situation] situation An instance of a {Riot::Situation} # @return [Array] array containing evaluation state and a descriptive explanation def run(situation) @expectings << situation.evaluate(&@expectation_block) if @expectation_block actual = situation.evaluate(&definition) assert((@macro.expects_exception? ? nil : actual), *@expectings) rescue Exception => e @macro.expects_exception? ? assert(e, *@expectings) : @macro.error(e) end private def enhance_with_macro(name, *expectings, &expectation_block) @expectings, @expectation_block = expectings, expectation_block @macro = self.class.macros[name.to_s].new raise(NoMethodError, name) unless @macro @macro.file, @macro.line = caller.first.match(/(.*):(\d+)/)[1..2] self end alias :method_missing :enhance_with_macro def assert(*arguments) @negative ? @macro.devaluate(*arguments) : @macro.evaluate(*arguments) end end # Assertion end # Riot riot-0.12.7/lib/riot/runnable.rb0000644000004100000410000000660212261222026016463 0ustar www-datawww-datamodule Riot # A runnable block is pretty much an anonymous block decorator. It's goal is to accept a block, a # description for what the block is intended to be for, and provide a +run+ method expects a # {Riot::Situation} instance. Any time a {Riot::Situation} is provided to +run+, a {Riot::RunnableBlock} # promises to evaluate itself against the situation in some way. # # Intent is to sub-class {Riot::RunnableBlock} with specific mechanisms for contorting the # {Riot::Situation}. class RunnableBlock # The decorated block. attr_reader :definition # Creates a new RunnableBlock. # # @param [String] description a description of what this block is for # @param [lambda] &definition the block to decorate def initialize(description, &definition) @description, @definition = description, definition || proc { false } end # Given a {Riot::Situation}, eval the provided block against it and then return a status tuple. # # @param [Riot::Situation] situation An instance of a {Riot::Situation} # @return [Array] array containing at least an evaluation state def run(situation) raise "Define your own run" end # String representation of this block, which is basically the description. # # @return [String] def to_s; @description; end end # RunnableBlock # Used to decorate a setup, hookup, a teardown or anything else that is about context administration. class Setup < RunnableBlock def initialize(&definition) super("setup", &definition) end # Calls {Riot::Situation#setup} with the predefined block at {Riot::Context} run-time. Though this is # like every other kind of {Riot::RunnableBlock}, +run+ will not return a meaningful state, which means # the reporter will likely not report anything. # # @param [Riot::Situation] situation the situation for the current {Riot::Context} run # @return [Array] array containing the evaluation state def run(situation) situation.setup(&definition) [:setup] rescue StandardError => e [:setup_error, e] end end # Setup # Used to decorate a helper. A helper generally ends up being a glorified method that can be referenced # from within a setup, teardown, hookup, other helpers, assertion blocks, and assertion macro blocks; # basically anywhere the {Riot::Situation} instance is available. # # context "Making dinner" do # helper(:easy_bake) do |thing| # EasyBake.new(thing, :ingredients => [:ketchup, :chocolate, :syrup]) # end # # setup do # easy_bake(:meatloaf) # end # # asserts(:food_poisoning_probabilty).equals(0.947) # end # Making dinner class Helper < RunnableBlock def initialize(name, &definition) super("helper #{name}", &definition) @name = name end # Calls {Riot::Situation#helper} with the predefined helper name and block at {Riot::Context} run-time. # Though this is like every other kind of {Riot::RunnableBlock}, +run+ will not return a meaningful # state, which means the reporter will likely not report anything. # # @param [Riot::Situation] situation the situation for the current {Riot::Context} run # @return [Array] array containing the evaluation state def run(situation) situation.helper(@name, &definition) [:helper] end end end # Riot riot-0.12.7/lib/riot/context_helpers.rb0000644000004100000410000001412012261222026020055 0ustar www-datawww-datamodule Riot module ContextHelpers # Add a setup block. # # A setup block defines the topic of the context. There can be multiple setup # blocks; each can access the previous topic through the +topic+ attribute. # # context "A string" do # setup { "foo" } # setup { topic * 2 } # asserts(:length).equals(6) # end # # If you provide +true+ as the first argument, the setup will be unshifted onto the list of setups, # ensuring it will be run before any other setups. This is really only useful for context middlewares. # # @param [Boolean] premium indicates importance of the setup # @return [Riot::Setup] def setup(premium=false, &definition) setup = Setup.new(&definition) premium ? @setups.unshift(setup) : @setups.push(setup) setup end # Helpers are essentially methods accessible within a situation. # # They're not setup methods, but can be called from setups or from assetions. Each time called, the # helper will be evaluated. It's not currently memoized. # # context "A string" do # helper(:foo) { "bar" } # asserts("a foo") { foo }.equals("bar") # end # # @param [String, Symbol] name the name of the helper # @return [Riot::Helper] def helper(name, &block) (@setups << Helper.new(name, &block)).last end # A setup shortcut that returns the original topic so you don't have to. Good for nested setups. Instead # of doing this in your context: # # setup do # topic.do_something # topic # end # # You would do this: # # hookup { topic.do_something } # Yay! # # @return [Riot::Setup] def hookup(&definition) setup { self.instance_eval(&definition); topic } end # Add a teardown block. You may define multiple of these as well. # # teardown { Bombs.drop! } # # @return [Riot::Setup] def teardown(&definition) (@teardowns << Setup.new(&definition)).last end # Makes an assertion. # # In the most basic form, an assertion requires a descriptive name and a block. # # asserts("#size is equals to 2") { topic.size == 2 } # # However, several shortcuts are available. Assertion macros can be added to the # end, automating a number of common assertion patterns, e.g. # # asserts("#size") { topic.size }.equals(2) # # Furthermore, the pattern of testing an attribute on the topic is codified as # # asserts(:size).equals(2) # # Or with arguments: # # asserts(:foo,1,2).equals(3) # # Passing a Symbol to +asserts+ enables this behaviour. For more information on # assertion macros, see {Riot::AssertionMacro}. # # @param [String, Symbol] what description of test or property to inspect on the topic # @return [Riot::Assertion] def asserts(*what, &definition) new_assertion("asserts", *what, &definition) end # Same as #asserts, except it uses the phrase "should" in the report output. Sometimes you feel like a # nut, sometimes you don't. # # should("ensure expected") { "bar" }.equals("bar") # # #should also has the same shortcuts available to #asserts: # # should(:bar,1,2).equals(3) # # @param [String, Symbol] what description of test or property to inspect on the topic # @return [Riot::Assertion] def should(*what, &definition) new_assertion("should", *what, &definition) end # Like an assertion, but expects negative results. # # In the most basic form, a denial requires a descriptive name and a block. # # denies("#size is equals to 2") { topic.size != 2 } # # Several shortcuts are available here as well. Assertion macros can be added to the # end, automating a number of common assertion patterns, e.g. # # denies("#size") { topic.size }.equals(2) # # Furthermore, the pattern of testing an attribute on the topic is codified as # # denies(:size).equals(2) # # the shorcut can also pass additional arguments to the method like: # # denies(:foo,1,3).equals(2) # # Passing a Symbol to +denies+ enables this behaviour. For more information on # assertion macros, see {Riot::AssertionMacro}. # # @param [String, Symbol] what description of test or property to inspect on the topic # @return [Riot::Assertion] def denies(*what, &definition) what << {:negative => true} new_assertion "denies", *what, &definition end # This is the negative form of #should. This is exactly like denies. Just here for syntactic sugar. # # A basic eample is: # # should_not("have size equal 2") { topic.size == 2 } # # In addition, the #denies shortcut as available as well: # # should_not(:size).equals 3 # # Or passing in arguments # # should_not(:foo,1,2).equals(2) # # @param [String,Symbol] what description or property to inspect on the topic # @return [Riot::Assertion] def should_not(*what, &definition) what << {:negative => true} new_assertion "should not", *what, &definition end # Makes an assertion on the topic itself, e.g. # # asserts_topic.matches(/^ab+/) # # @param [String] what description of test # @return [Riot::Assertion] def asserts_topic(what="that it") asserts(what) { topic } end # Makes a negative assertion on the topic itself, e.g. # # denies_topic.matches(/^ab+/) # # @param [String] what description of test # @return [Riot::Assertion] def denies_topic(what="that it") denies(what) { topic } end private def new_assertion(scope, *args, &definition) options = args.extract_options! definition ||= proc { topic.send(*args) } description = "#{scope} #{args.first}" description << " with arguments(s): #{args.slice(1, args.length).inspect}" if args.size > 1 (@assertions << assertion_class.new(description, options[:negative], &definition)).last end end # AssertionHelpers end # Riot riot-0.12.7/lib/riot/reporter/0000755000004100000410000000000012261222026016166 5ustar www-datawww-datariot-0.12.7/lib/riot/reporter/story.rb0000644000004100000410000000345112261222026017676 0ustar www-datawww-datamodule Riot # For each context that is started and assertion that is run, its description is printed to the console # on its own line. Regarding assertions, if ansi-colors are available then passing assertions are printed # in green, failing in yellow, and errors in red. Note that backtraces are not reported for errors; see # {Riot::VerboseStoryReporter}. class StoryReporter < IOReporter # Prints the descrition of the context on its own line # # @param (see Riot::Reporter#describe_context) def describe_context(context) super puts context.detailed_description end # Prints the description of the assertion. Prints in green if possible. # # @param (see Riot::Reporter#pass) def pass(description, message) puts " + " + green("#{description} #{message}".strip) end # Prints the description of the assertion and the line number of the failure. Prints in yellow if # possible. # # @param (see Riot::Reporter#fail) def fail(description, message, line, file) puts " - " + yellow("#{description}: #{message} #{line_info(line, file)}".strip) end # Prints the description of the assertion and the exception message. Prints in red if # possible. # # @param (see Riot::Reporter#error) def error(description, e) puts " ! " + red("#{description}: #{e.message}") end end # StoryReporter # Same as {Riot::StoryReporter} except that backtraces are printed for assertions with errors class VerboseStoryReporter < StoryReporter # Prints the description of the assertion and the exception backtrace. Prints in red if # possible. # # @param (see Riot::Reporter#error) def error(description, e) super puts red(format_error(e)) end end # VerboseStoryReporter end # Riot riot-0.12.7/lib/riot/reporter/dot_matrix.rb0000644000004100000410000000314112261222026020664 0ustar www-datawww-datamodule Riot # Outputs in the dot-notion almost everyone should be familiar with, "." implies pass, "F" implies a # failure, and "E" implies an error. If ansi-coloring is available, it is used. Error and failure messages # are buffered for output until the end. class DotMatrixReporter < IOReporter # Creates a new DotMatrixReporter and initializes the failure/error details buffer. # @param (see Riot::IOReporter#initialize) def initialize(*args) super @details = [] end # Prints a ".". Prints in green if possible. # # @param (see Riot::Reporter#pass) def pass(description, message) print green(".") end # Prints a "F" and saves the failure details (including line number and file) for the end. # Prints in yellow if possible. # # @param (see Riot::Reporter#fail) def fail(description, message, line, file) print yellow("F") @details << "FAILURE - #{test_detail(description, message)} #{line_info(line, file)}".strip end # Prints a "E" and saves the error details (including backtrace) for the end. Prints in red if possible. # # @param (see Riot::Reporter#error) def error(description, e) print red("E") @details << "ERROR - #{test_detail(description, format_error(e))}" end # (see Riot::Reporter#results) def results(time_taken) puts "\n#{@details.join("\n\n")}" unless @details.empty? super end private def test_detail(description, message) "#{current_context.detailed_description} #{description} => #{message}" end end # DotMatrixReporter end # Riot riot-0.12.7/lib/riot/reporter/silent.rb0000644000004100000410000000070712261222026020015 0ustar www-datawww-datamodule Riot # Basically, the Null Object pattern; nothing is output from this reporter. class SilentReporter < Reporter # (see Riot::Reporter#pass) def pass(description, message); end # (see Riot::Reporter#fail) def fail(description, message, line, file); end # (see Riot::Reporter#error) def error(description, e); end # (see Riot::Reporter#results) def results(time_taken); end end # SilentReporter end # Riot riot-0.12.7/lib/riot/reporter/pretty_dot_matrix.rb0000644000004100000410000000235412261222026022300 0ustar www-datawww-datamodule Riot # This is essentially just DotMatrix with the legacy DotMatrix formatting, slightly better. # Failure and Error outputs are color labeled and are formatted neatly and # concisely under each associated label. # example: # ........FE.... # FAILURE # A failure would have a message like this => expected 1, not 0 # (on line 26 in test/core/blah.rb) # ERROR # A reporter asserts this errors => Exception occured # at test/core/report_test.rb:24:in `block (2 levels) in ' # class PrettyDotMatrixReporter < DotMatrixReporter # Prints a yellow F and formats the Fail messages a bit better # than the default DotMatrixReporter def fail(description, message, line, file) print yellow('F') @details << "#{yellow("FAILURE")}\n #{test_detail(description, message)}\n #{line_info(line, file)}".strip end # Prints out an red E and formats the fail message better def error(description, e) print red('E') @details << "#{red("ERROR")}\n #{test_detail(description,"#{e} occured")}\n #{simple_error(e)}" end def simple_error(e) format = [] filter_backtrace(e.backtrace) { |line| format << "at #{line}" } format.join("\n") end end end riot-0.12.7/lib/riot/reporter/io.rb0000644000004100000410000000612112261222026017122 0ustar www-datawww-datamodule Riot # An IOReporter is one that expects to use an IO object to output results to. Thus, whatever is available # by an instance of an IO object should be available to whatever is given to this reporter to use. # # This is an abstract class. You should use some other or define your own sub-class that knows how to # handle +pass+, +fail+, and +error+. class IOReporter < Reporter # Creates a new IOReporter. You can give it your own IO writer or it will default to +STDOUT+. # If you want to specifically turn colorization off in the output, pass the +plain+ option. # # @param [IO] writer the writer to use for results # @param [Hash] options options for reporter def initialize(*args) super @options = args.extract_options! @writer = (args.shift || STDOUT) end # (see Riot::Reporter#results) def results(time_taken) values = [passes, failures, errors, ("%0.6f" % time_taken)] puts "\n%d passes, %d failures, %d errors in %s seconds" % values end protected # Helper that knows how to write output to the writer with a newline. # # @param [String] message the message to be printed def puts(message) @writer.puts(message); end # Helper that knows how to write output to the writer without a newline. # # @param [String] message the message to be printed def print(message) @writer.print(message); end # Takes a line number, the file it corresponds to, and generates a formatted string for use in failure # responses. # # @param [Number] line the line number of the failure # @param [String] file the name of the file the failure was in # @return [String] formatted failure line def line_info(line, file) line ? "(on line #{line} in #{file})" : "" end # Generates a message for assertions that error out. However, in the additional stacktrace, any mentions # of Riot and Rake framework methods calls are removed. Makes for a more readable error response. # # @param [Exception] e the exception to generate the backtrace from # @return [String] the error response message def format_error(e) format = [" #{e.class.name} occurred", "#{e.to_s}"] filter_backtrace(e.backtrace) { |line| format << " at #{line}" } format.join("\n") end # Filters Riot and Rake method calls from an exception backtrace. # # @param [Array] backtrace an exception's backtrace # @param [lambda] &line_handler called each time a good line is found def filter_backtrace(backtrace, &line_handler) backtrace.reverse_each do |bt| yield bt unless (bt =~ /(\/lib\/riot|rake_test_loader)/) end end # Color output def red(str); with_color(31, str); end def yellow(str); with_color(33, str); end def green(str); with_color(32, str); end def plain? (@options[:plain] || @options["plain"]) end # for color reference: # http://www.pixelbeat.org/docs/terminal_colours/ def with_color(code,str) plain? ? str : "\e[#{code}m#{str}\e[0m" end end # IOReporter end # Riot riot-0.12.7/lib/riot/version.rb0000644000004100000410000000004612261222026016336 0ustar www-datawww-datamodule Riot VERSION = "0.12.7" end riot-0.12.7/lib/riot/middleware.rb0000644000004100000410000001134012261222026016765 0ustar www-datawww-datamodule Riot # Context middlewares are chainable, context preparers. This to say that a middleware knows about a single # neighbor and that it can prepare context before the context is "run". As a for instance, suppose you # wanted the following to be possible. # # context Person do # denies(:valid?) # end # Person # # Without writing a middleware, the topic in this would actually be nil, but what the context is saying is # that there should be something in the topic that responds to +:valid?+; an instance of +Person+ in this # case. We can do this with middleware like so: # # class Modelware < Riot::ContextMiddleware # register # # def call(context) # if context.description.kind_of?(Model) # context.setup { context.description.new } # end # middleware.call(context) # end # end # Modelware # # That's good stuff. If you're familiar at all with the nature of Rack middleware - how to implement it, # how it's executed, etc. - you'll be familiar with Context middleware as the principles are similar: # # 1. Define a class that extends {Riot::ContextMiddleware} # 2. Call +register+ # 3. Implement a +call+ method that accepts the Context that is about to be executed # 4. Do stuff, but make sure to pass the call along with +middleware.call(context)+ # # Steps 1, 2, and 3 should be pretty straight-forward. Currently, +context+ is the only argument to +call+. # When your middleware is initialized it is given the next registered middleware in the chain (which is # where the `middleware` method gets its value from). # # So, "Do stuff" from step 4 is the where we start breaking things down. What can you actually do? Well, # you can do anything to the context that you could do if you were writing a Riot test; and I do mean # anything. # # * Add setup blocks (as many as you like) # * Add teardown blocks (as many as you like) # * Add hookup blocks (as many as you like) # * Add helpers (as many as you like) # * Add assertions # # The context in question will not run before all middleware have been applied to the context; this is # different behavior than that of Rack middleware. {Riot::ContextMiddleware} is only about preparing a # context, not about executing it. Thus, where in your method you actually pass the call off to the next # middleware in the chain has impact on how the context is set up. Basically, whatever you do before # calling `middleware.call(context)` is done before any other middleware gets setup and before the innards # of the context itself are applied. Whatever you do after that call is done after all that, but still # before the actual setups, hookups, assertions, and teardowns are run. # # Do not expect the same instance of middleware to exist from one {Riot::Context} instance to the next. It # is highly likely that each {Riot::Context} will instantiate their own middleware instances. class ContextMiddleware # Registers the current middleware class with Riot so that it may be included in the set of middlewares # Riot will poke before executing a Context. # # class MyContextMiddleware < Riot::ContextMiddleware # register # def call(context) # context.setup { ... } # middleware.call(context) # this can go anywhere # context.hookup { ... } # end # end def self.register Context.middlewares << self end # Theoretically, the next middleware in the stack attr_reader :middleware # Create a new middleware instance and give it the next middleware in the chain. # # @param [Riot::ContextMiddleware] middleware the next middleware instance in the chain def initialize(middleware) @middleware = middleware end # The magic happens here. Because you have access to the Context, you can add your own setups, hookups, # etc. +call+ will be called before any tests are run, but after the Context is configured. Though # something will likely be returned, do not put any faith in what that will be. # # @param [Riot::Context] context the Context instance that will be prepared by registered middleware def call(context) raise "You should implement call yourself" end end # ContextMiddleware # Special middleware used by Context directly. It will always be the last in the chain and is the actual # place where the user's runtime context is processed. class AllImportantMiddleware < ContextMiddleware def initialize(&context_definition) @context_definition = context_definition end # (see Riot::ContextMiddleware#call) def call(context) context.instance_eval(&@context_definition); end end # AllImportantMiddleware end # Riot riot-0.12.7/lib/riot/message.rb0000644000004100000410000000721512261222026016302 0ustar www-datawww-datamodule Riot class BlankSlate instance_methods.each do |meth| undef_method(meth) unless meth.to_s =~ /^(__|object_id)/ end end # A Message is similar in nature (but not implementation) to a string buffer; you put some strings in and # calling {#to_s} will generate a single new string. What's special abnout Message is how you get strings # into it. By convention, any method called on a Message that isn't defined will have its name turned into # a string and any underscores replaced with spaces. This happens for each method call and those small # messages are chained together at the end. For instance: # # message = Riot::Message.new # message.hello_world.to_s # => "hello world" # # message.whats_the_news.to_s # => "hello world whats the news" # # For every method called it is also acceptable to pass any number of arguments. These arguments will be # added to the final message after having `inspect` called on them. Another for instance: # # message = Riot::Message.new # message.expected([1, 2, 3], "foo").not([3, 2, 1], "bar") # message.to_s # => 'expected [1, 2, 3], "foo", not [3, 2, 1], "bar"' # # This is useful for - and was originally intended for - generating pass/fail messages from # {Riot::AssertionMacro assertion macros}. class Message < BlankSlate # Creates a new Message instance. # # @param [Array] *phrases an array of objects to be inspected def initialize(*phrases) @chunks = [] _inspect(phrases) end # Generates the string value of the built-up message. # # @return [String] def to_s; @chunks.join.strip; end alias_method :inspect, :to_s # Converts any method call into a more readable string by replacing underscores with spaces. Any # arguments to the method are inspected and appended to the final message. Blocks are currently ignored. # # @param [String, Symbol] meth the method name to be converted into a more readable form # @param [Array] *phrases an array of objects to be inspected # @return [Riot::Message] this instance for use in chaining calls def method_missing(meth, *phrases, &block) push(meth.to_s.gsub('_', ' ')) _inspect(phrases) end # Adds a comma then the provided phrase to this message. # # Riot::Message.new.hello.comma("world").to_s # => "hello, world" # # @param [String] str any string phrase to be added after the comma # @param [Array] *phrases an array of objects to be inspected # @return [Riot::Message] this instance for use in chaining calls def comma(str, *phrases) _concat([", ", str]) _inspect(phrases) end # Adds the string ", but". # # Riot::Message.new.any_number.but(52).to_s # => "any number, but 52" # # @param [Array] *phrases an array of objects to be inspected # @return [Riot::Message] this instance for use in chaining calls def but(*phrases); comma("but", *phrases); end # Adds the string ", not". # # Riot::Message.new.expected_freebies.not("$1.50").to_s # => 'expected freebies, not "$1.50"' # # @param [Array] *phrases an array of objects to be inspected # @return [Riot::Message] this instance for use in chaining calls def not(*phrases); comma("not", *phrases); end private def push(str) _concat([" ", str]) end def _concat(chunks) @chunks.concat(chunks) self end def _inspect(phrases) unless phrases.empty? push(phrases.map { |phrase| phrase.inspect }.join(", ")) end self end end # Message end # Riot riot-0.12.7/lib/riot/assertion_macros/0000755000004100000410000000000012261222026017677 5ustar www-datawww-datariot-0.12.7/lib/riot/assertion_macros/kind_of.rb0000644000004100000410000000200212261222026021627 0ustar www-datawww-datamodule Riot # Asserts that the result of the test is an object that is a kind of the expected type # # asserts("test") { "foo" }.kind_of(String) # should("test") { "foo" }.kind_of(String) # # You can also test the result is not a kind of a thing: # # denies("test") { "foo" }.kind_of(Boolean) class KindOfMacro < AssertionMacro register :kind_of # (see Riot::AssertionMacro#evaluate) # @param [Class] expected the expected class of actual def evaluate(actual, expected) if actual.kind_of?(expected) pass new_message.is_a_kind_of(expected) else fail expected_message.kind_of(expected).not(actual.class) end end # (see Riot::AssertionMacro#devaluate) # @param [Class] expected the unexpected class of actual def devaluate(actual, expected) if actual.kind_of?(expected) fail expected_message.not_kind_of(expected).not(actual.class) else pass new_message.is_a_kind_of(expected) end end end end riot-0.12.7/lib/riot/assertion_macros/exists.rb0000644000004100000410000000231312261222026021542 0ustar www-datawww-datamodule Riot # Asserts that the result of the test is a non-nil value. This is useful in the case where you don't want # to translate the result of the test into a boolean value # # asserts("test") { "foo" }.exists # should("test") { 123 }.exists # asserts("test") { "" }.exists # asserts("test") { nil }.exists # This would fail # # You can also test for non-existince (being nil), but if you would better if you used the +nil+ macro: # # denies("test") { nil }.exists # would pass # asserts("test") { nil }.nil # same thing # # denies("test") { "foo" }.exists # would fail # # @deprecated Please use +denies.nil+ instead of +asserts.exists+. class ExistsMacro < AssertionMacro register :exists # (see Riot::AssertionMacro#evaluate) def evaluate(actual) warn "exists is deprecated; please use denies.nil instead of asserts.exists" actual.nil? ? fail("expected a non-nil value") : pass("does exist") end # (see Riot::AssertionMacro#devaluate) def devaluate(actual) warn "exists is deprecated; please use denies.nil instead of asserts.exists" actual.nil? ? pass("does exist") : fail("expected a nil value") end end end riot-0.12.7/lib/riot/assertion_macros/includes.rb0000644000004100000410000000223412261222026022033 0ustar www-datawww-datamodule Riot # Asserts the result contains the expected element # # asserts("a string") { "world" }.includes('o') # asserts("an array") { [1,2,3] }.includes(2) # asserts("a range") { (1..15) }.includes(10) # # You can also assert that the result does not contain an element: # # denies("a string") { "world" }.includes('f') # denies("an array") { [1,2,3,4,5] }.includes(0) # denies("a range") { (1..15) }.includes(16) class IncludesMacro < AssertionMacro register :includes # (see Riot::AssertionMacro#evaluate) # @param [Object] expected the object that is expected to be included def evaluate(actual, expected) if actual.include?(expected) pass new_message.includes(expected) else fail expected_message(actual).to_include(expected) end end # (see Riot::AssertionMacro#devaluate) # @param [Object] expected the object that is not expected to be included def devaluate(actual, expected) if actual.include?(expected) fail expected_message(actual).to_not_include(expected) else pass new_message.includes(expected) end end end end riot-0.12.7/lib/riot/assertion_macros/equals.rb0000644000004100000410000000227612261222026021525 0ustar www-datawww-datamodule Riot # In the positive case, asserts that the result of the test equals the expected value. Using the +==+ # operator to assert equality. # # asserts("test") { "foo" }.equals("foo") # should("test") { "foo" }.equals("foo") # asserts("test") { "foo" }.equals { "foo" } # # In the negative case, asserts that the result of the test *does not* equal the expected value. Using the # +==+ operator. # # denies("test") { "foo" }.equals("bar") # denies("test") { "foo" }.equals { "bar" } class EqualsMacro < AssertionMacro register :equals # (see Riot::AssertionMacro#evaluate) # @param [Object] expected the object value to compare actual to def evaluate(actual, expected) if expected == actual pass new_message.is_equal_to(expected) else fail expected_message(expected).not(actual) end end # (see Riot::AssertionMacro#devaluate) # @param [Object] expected the object value to compare actual to def devaluate(actual, expected) if expected != actual pass new_message.is_equal_to(expected).when_it_is(actual) else fail new_message.did_not_expect(actual) end end end end riot-0.12.7/lib/riot/assertion_macros/same_elements.rb0000644000004100000410000000226312261222026023050 0ustar www-datawww-datamodule Riot # Asserts that two arrays contain the same elements, the same number of times. # # asserts("test") { ["foo", "bar"] }.same_elements(["bar", "foo"]) # should("test") { ["foo", "bar"] }.same_elements(["bar", "foo"]) # # Maybe you just want to make sure two sets arent't the same: # # denies("test") { ["foo", "bar"] }.same_elements(["baz", "boo"]) class SameElementsMacro < AssertionMacro register :same_elements require 'set' # (see Riot::AssertionMacro#evaluate) # @param [Object] expected the collection of elements that actual should be equivalent to def evaluate(actual, expected) same = (Set.new(expected) == Set.new(actual)) same ? pass(new_message.has_same_elements_as(expected)) : fail(expected_message.elements(expected).to_match(actual)) end # (see Riot::AssertionMacro#devaluate) # @param [Object] expected the collection of elements that actual should not be equivalent to def devaluate(actual, expected) same = (Set.new(expected) == Set.new(actual)) same ? fail(expected_message.elements(expected).not_to_match(actual)) : pass(new_message.has_same_elements_as(expected)) end end end riot-0.12.7/lib/riot/assertion_macros/raises.rb0000644000004100000410000000574412261222026021524 0ustar www-datawww-datamodule Riot # Asserts that the test raises the expected Exception # asserts("test") { raise My::Exception }.raises(My::Exception) # should("test") { raise My::Exception }.raises(My::Exception) # # You can also check to see if the provided message equals or matches your expectations. The message # from the actual raised exception will be converted to a string before any comparison is executed. # asserts("test") { raise My::Exception, "Foo" }.raises(My::Exception, "Foo") # asserts("test") { raise My::Exception, "Foo Bar" }.raises(My::Exception, /Bar/) # # In the negative case, you can test that an exception was not raised or that if an exception was raised # that the type of exception was different (sounds confusing). # # denies("test") { "foo" }.raises(Exception) # would pass # denies("test") { raise Exception }.raises(My::Exception) # would pass # denies("test") { raise Exception }.raises(Exception) # would fail class RaisesMacro < AssertionMacro register :raises expects_exception! # (see Riot::AssertionMacro#evaluate) # @param [Class] expected_class the expected Exception class # @param [String, nil] expected_message an optional exception message or message partial def evaluate(actual_exception, expected_class, expected_message=nil) actual_message = actual_exception && actual_exception.message if actual_exception.nil? fail new_message.expected_to_raise(expected_class).but.raised_nothing elsif expected_class != actual_exception.class fail new_message.expected_to_raise(expected_class).not(actual_exception.class) elsif expected_message && !(actual_message.to_s =~ %r[#{expected_message}]) fail expected_message(expected_message).for_message.not(actual_message) else message = new_message.raises(expected_class) pass(expected_message ? message.with_message(expected_message) : message) end end # evaluate # (see Riot::AssertionMacro#devaluate) # @param [Class] expected_class the unexpected Exception class # @param [String, nil] expected_message an optional exception message or message partial def devaluate(actual_exception, expected_class, expected_message=nil) actual_message = actual_exception && actual_exception.message if actual_exception.nil? pass new_message.raises(expected_class) elsif expected_class != actual_exception.class if expected_message && !(actual_message.to_s =~ %r[#{expected_message}]) pass new_message.raises(expected_class).with_message(expected_message) else pass new_message.raises(expected_class) end else message = new_message.expected_to_not_raise(expected_class) if expected_message fail message.with_message(expected_message).but.raised(actual_exception.class). with_message(actual_exception.message) else fail message end end end # devaluate end # RaisesMacro end riot-0.12.7/lib/riot/assertion_macros/matches.rb0000644000004100000410000000227112261222026021652 0ustar www-datawww-datamodule Riot # Asserts that the result of the test equals matches against the proved expression # # asserts("test") { "12345" }.matches(/\d+/) # should("test") { "12345" }.matches(/\d+/) # # You can also test that the result does not match your regex: # # denies("test") { "hello, world"}.matches(/\d+/) class MatchesMacro < AssertionMacro register :matches # (see Riot::AssertionMacro#evaluate) # @param [Regex, String] expected the string or regex to be used in comparison def evaluate(actual, expected) expected = %r[#{Regexp.escape(expected)}] if expected.kind_of?(String) if actual.to_s =~ expected pass(new_message.matches(expected)) else fail(expected_message(expected).to_match(actual)) end end # (see Riot::AssertionMacro#devaluate) # @param [Regex, String] expected the string or regex to be used in comparison def devaluate(actual, expected) expected = %r[#{Regexp.escape(expected)}] if expected.kind_of?(String) if actual.to_s =~ expected fail(expected_message(expected).not_to_match(actual)) else pass(new_message.matches(expected)) end end end end riot-0.12.7/lib/riot/assertion_macros/nil.rb0000644000004100000410000000126512261222026021012 0ustar www-datawww-datamodule Riot # Asserts that the result of the test is nil # # asserts("test") { nil }.nil # should("test") { nil }.nil # # You could test that the result is not nil, but it would make more sense to use the +exists+ macro: # # denies("test") { "foo" }.nil # asserts("test") { "foo" }.exists class NilMacro < AssertionMacro register :nil # (see Riot::AssertionMacro#evaluate) def evaluate(actual) actual.nil? ? pass("is nil") : fail(expected_message.nil.not(actual)) end # (see Riot::AssertionMacro#devaluate) def devaluate(actual) actual.nil? ? fail(expected_message.is_nil.not('non-nil')) : pass("is nil") end end end riot-0.12.7/lib/riot/assertion_macros/empty.rb0000644000004100000410000000147012261222026021364 0ustar www-datawww-datamodule Riot # In the postive case, asserts the result of the test is empty. # # asserts("a string") { "" }.empty # asserts("an array") { [] }.empty # asserts("a hash") { Hash.new }.empty # # In the negative case, asserts the result of the test is not empty. # # denies("a string") { "foo" }.empty # denies("an array") { [1] }.empty # denies("a hash") { {:foo => "bar" } }.empty class EmptyMacro < AssertionMacro register :empty # (see Riot::AssertionMacro#evaluate) def evaluate(actual) actual.empty? ? pass(new_message.is_empty) : fail(expected_message(actual).to_be_empty) end # (see Riot::AssertionMacro#devaluate) def devaluate(actual) actual.empty? ? fail(expected_message(actual).to_not_be_empty) : pass(new_message.is_empty) end end end riot-0.12.7/lib/riot/assertion_macros/raises_kind_of.rb0000644000004100000410000000675112261222026023214 0ustar www-datawww-datamodule Riot # Asserts that the test raises the expected exception, or one of its # subclasses. Thus, the following assertions pass: # asserts("test") { raise My::Exception }.raises(My::Exception) # should("test") { raise My::Exception }.raises(My::Exception.superclass) # The following, however, fails: # asserts("test") { raise My::Exception.superclass }.raises(My::Exception) # # You can also check to see if the provided message equals or matches your # expectations. The message from the actual raised exception will be converted # to a string before any comparison is executed. # asserts("test") { raise My::Exception, "Foo" }.raises(My::Exception, "Foo") # asserts("test") { raise My::Exception, "Foo Bar" }.raises(My::Exception, /Bar/) # # You can use the negative form to assert that no exception is raised at all: # denies("test") { # # do stuff # }.raises_kind_of Exception # # It can be used to check that a particular class of exception is not raised, # in which case you should be aware that raising another kind of exception # will *not* produce a failure. # denies("test") { raises ArgumentError }.raises_kind_of ArgumentError # fails # denies("test") { raises Class.new(ArgumentError) }.raises_kind_of ArgumentError # fails # denies("test") { raises "this doesn't work" }.raises_kind_of ArgumentError # passes class RaisesKindOfMacro < AssertionMacro register :raises_kind_of expects_exception! # (see Riot::AssertionMacro#evaluate) # @param [Class] expected_class the expected Exception class # @param [String, nil] expected_message an optional exception message or message partial def evaluate(actual_exception, expected_class, expected_message=nil) actual_message = actual_exception && actual_exception.message if !actual_exception fail new_message.expected_to_raise_kind_of(expected_class).but.raised_nothing elsif !actual_exception.is_a?(expected_class) fail new_message.expected_to_raise_kind_of(expected_class).not(actual_exception.class) elsif expected_message && !(actual_message.to_s =~ %r[#{expected_message}]) fail expected_message(expected_message).for_message.not(actual_message) else message = new_message.raises_kind_of(expected_class) pass(expected_message ? message.with_message(expected_message) : message) end end # evaluate # (see Riot::AssertionMacro#devaluate) # @param [Class] expected_class the unexpected Exception class # @param [String, nil] expected_message an optional exception message or message partial def devaluate(actual_exception, expected_class, expected_message=nil) actual_message = actual_exception && actual_exception.message if !actual_exception pass new_message.raises_kind_of(expected_class) elsif !actual_exception.is_a?(expected_class) if expected_message && !(actual_message.to_s =~ %r[#{expected_message}]) pass new_message.raises_kind_of(expected_class). with_message(expected_message) else pass new_message.raises_kind_of(expected_class) end else message = new_message.expected_to_not_raise_kind_of(expected_class) if expected_message fail message.with_message(expected_message).but. raised(actual_exception.class). with_message(actual_exception.message) else fail message end end end # devaluate end # RaisesMacro end riot-0.12.7/lib/riot/assertion_macros/assigns.rb0000644000004100000410000000554212261222026021701 0ustar www-datawww-datamodule Riot # In the positive case, asserts that an instance variable is defined for the result of the assertion. # Value of instance variable is expected to not be nil. # # setup { User.new(:email => "foo@bar.baz") } # asserts_topic.assigns(:email) # # If a value is provided in addition to the variable name, the actual value of the instance variable # must equal the expected value. # # setup { User.new(:email => "foo@bar.baz") } # asserts_topic.assigns(:email, "foo@bar.baz") # # In the negative case, asserts that an instance variables *is not* defined or has a nil value. If a value # is provided in addition to the name, then ensure that the actual value does not equal the expected value. # # setup { User.new(:email => "foo@bar.baz") } # denies("topic") { topic }.assigns(:first_name) # denies("topic") { topic }.assigns(:email, "bar@baz.boo") class AssignsMacro < AssertionMacro register :assigns # (see Riot::AssertionMacro#evaluate) # @param [Symbol, String] variable name of instance variable to look for # @param [Object, nil] expected_value an optional value to validate for the variable def evaluate(actual, *expectings) prepare(actual, *expectings) do |variable, expected_value, actual_value| if actual_value.nil? fail expected_message(variable).to_be_assigned_a_value elsif !expected_value.nil? && expected_value != actual_value fail expected_message(variable).to_be_assigned_with(expected_value).not(actual_value) else if expected_value && actual_value pass new_message.assigns(variable).with(expected_value) else pass new_message.assigns(variable) end end end end # (see Riot::AssertionMacro#devaluate) # @param [Symbol, String] variable name of instance variable to look for # @param [Object, nil] expected_value an optional value to validate for the variable def devaluate(actual, *expectings) prepare(actual, *expectings) do |variable, expected_value, actual_value| if actual_value.nil? || (expected_value && expected_value != actual_value) if expected_value && actual_value pass new_message.assigns(variable).with(expected_value) else pass new_message.assigns(variable) end else message = expected_message(variable).to_not_be fail(expected_value.nil? ? message.assigned_a_value : message.assigned_with(expected_value)) end end end private def prepare(actual, *expectings, &block) variable, expected_value = expectings var_name = "@#{variable}" var_value = actual.instance_variable_defined?(var_name) ? actual.instance_variable_get(var_name) : nil yield(variable, expected_value, var_value) end end # AssignsMacro end # Riot riot-0.12.7/lib/riot/assertion_macros/respond_to.rb0000644000004100000410000000215212261222026022400 0ustar www-datawww-datamodule Riot # Asserts that the result of the test is an object that responds to the given method # # asserts("test") { "foo" }.respond_to(:to_s) # should("test") { "foo" }.respond_to(:to_s) # # If you want to test that the result does not respond to something: # # denies("test") { "foo" }.responds_to(:harassment) class RespondToMacro < AssertionMacro register :respond_to register :responds_to # (see Riot::AssertionMacro#evaluate) # @param [Symbol, String] expected the method name that actual should respond to def evaluate(actual, expected) if actual.respond_to?(expected) pass(new_message.responds_to(expected)) else fail(expected_message.method(expected).is_not_defined) end end # (see Riot::AssertionMacro#devaluate) # @param [Symbol, String] expected the method name that actual should not respond to def devaluate(actual, expected) if actual.respond_to?(expected) fail(expected_message.method(expected).is_defined) else pass new_message.responds_to(expected) end end end end riot-0.12.7/lib/riot/assertion_macros/equivalent_to.rb0000644000004100000410000000244012261222026023103 0ustar www-datawww-datamodule Riot # Asserts that the result of the test is equivalent to the expected value. Using the +===+ operator. # # asserts("test") { "foo" }.equivalent_to(String) # should("test") { "foo" }.equivalent_to("foo") # asserts("test") { "foo" }.equivalent_to { "foo" } # # You can also assert that the expected value is not equivalent to something else: # # denies("test") { "foo" }.equivalent_to(Boolean) # denies("test") { "foo" }.equivalent_to("bar") # # Underneath the hood, this assertion macro uses: # # expected === actual class EquivalentToMacro < AssertionMacro register :equivalent_to # (see Riot::AssertionMacro#evaluate) # @param [Object] expected the object value to compare actual to def evaluate(actual, expected) if expected === actual pass new_message.is_equivalent_to(expected) else fail expected_message(actual).to_be_equivalent_to(expected) end end # (see Riot::AssertionMacro#devaluate) # @param [Object] expected the object value to compare actual to def devaluate(actual, expected) if expected === actual fail expected_message(actual).not_to_be_equivalent_to(expected) else pass new_message.is_equivalent_to(expected) end end end end riot-0.12.7/lib/riot/assertion_macros/any.rb0000644000004100000410000000211312261222026021010 0ustar www-datawww-datamodule Riot # In the positive case, asserts the result has items using the +any?+ operator. # # asserts("an array") { [1] }.any # asserts("a hash") { {:name => 'washington'} }.any # # In the negative case, asserts the result has no items using the +any?+ operator. # # denies("an empty array") { [] }.any # denies("an empty hash") { {} }.any # # @deprecated Please use +asserts.empty+ or +denies.empty+ instead. class AnyMacro < AssertionMacro register :any # (see Riot::AssertionMacro#evaluate) def evaluate(actual) warn "any is deprecated; please use asserts.empty or denies.empty instead" any?(actual) ? pass("has items") : fail(expected_message(actual).to_have_items) end # (see Riot::AssertionMacro#devaluate) def devaluate(actual) warn "any is deprecated; please use asserts.empty or denies.empty instead" any?(actual) ? fail(expected_message(actual).not_to_have_items) : pass("has items") end private def any?(object) object.kind_of?(String) ? object.length > 0 : object.any? end end end riot-0.12.7/lib/riot/assertion_macros/size.rb0000644000004100000410000000233112261222026021175 0ustar www-datawww-datamodule Riot # Asserts that result's size is as expected. Expected size can be specified as # a number or a range. # # asserts("a string") { 'washington' }.size(9..12) # asserts("an array") { [1, 2, 3] }.size(3) # asserts("a hash") { {:name => 'washington'} }.size(1) # # To ensure that the result is not of a specific size: # # denies("a string") { 'washington' }.size(4) # denies("an array") { [1, 2, 3] }.size(6..10) # denies("a hash") { {:name => 'washington'} }.size(2) class SizeMacro < AssertionMacro register :size # (see Riot::AssertionMacro#evaluate) # @param [Number] expected the expected size of actual def evaluate(actual, expected) failure_message = expected_message.size_of(actual).to_be(expected).not(actual.size) expected === actual.size ? pass(new_message.is_of_size(expected)) : fail(failure_message) end # (see Riot::AssertionMacro#devaluate) # @param [Number] expected the unexpected size of actual def devaluate(actual, expected) failure_message = expected_message.size_of(actual).to_not_be(expected).not(actual.size) expected === actual.size ? fail(failure_message) : pass(new_message.is_size(expected)) end end end riot-0.12.7/lib/riot/rr.rb0000644000004100000410000000460612261222026015302 0ustar www-datawww-datarequire 'rr' module Riot # Enables inherent RR support in Riot. When required in, all contexts and assertions are adapted to have # RR support. module RR # Basically, provides a {Riot::Situation} that has been adapted to RR. This means that any of the # RR methods that would typically be used: +mock+, +stub+, +verify+, etc. will be available to any # setup, yeardown, helper, hookup, or assertion. class Situation < Riot::Situation include ::RR::Adapters::RRMethods def initialize self.reset super end end # Situation # Binds the {Riot::Assertion} to RR so that successes and failures found by RR are inherently handled # during an assertion evaluation. In effect, if RR suggests failure during validation, the assertion # will fail and report these failures. class Assertion < Riot::Assertion # Adds RR support to {Riot::Assertion#run}. The basic flow is to: # * run the test as normal # * ask RR to verify mock results # * report any errors or return the result of the assertion as normal # * reset RR so that the next assertion in the context can be verified cleanly. # # @param (see Riot::Assertion#run) # @return (see Riot::Assertion#run) def run(situation) result = super situation.verify result rescue ::RR::Errors::RRError => e result.first == :pass ? [:fail, e.message.gsub(/\n/, " ")] : result ensure situation.reset end end # Assertion # Redefines the classes {Riot::Context} will use when creating new assertions and situations to be the # ones provided RR support. See {Riot::RR::Assertion} and {Riot::RR::Situation}. module ContextClassOverrides # (see Riot::ContextClassOverrides#assertion_class) def assertion_class; Riot::RR::Assertion; end # (see Riot::ContextClassOverrides#situation_class) def situation_class; Riot::RR::Situation; end end # ContextClassOverrides # A convenience method for telling {Riot::RR::ContextClassOverrides} to mix itself into {Riot::Context}. # Thus, enabling RR support in Riot. # # @param [Class] context_class the class representing the Context to bind to def self.enable(context_class) context_class.instance_eval { include Riot::RR::ContextClassOverrides } end end # RR end # Riot Riot::RR.enable(Riot::Context) riot-0.12.7/lib/riot/context_options.rb0000644000004100000410000000160112261222026020106 0ustar www-datawww-datamodule Riot module ContextOptions # Set options for the specific context. These options will generally be used for context middleware. # Riot::Context does not currently look at any options. # # context "Foo" do # set :transactional, true # end # # @param [Object] key the key used to look up the option value later # @param [Object] value the option value to store def set(key, value) option_set[key] = value end # Returns the value of a set option. The key must match exactly, symbols and strings are not # interchangeable. # # @param [Object] key the key used to look up the option value # @return [Object] def option(key) option_set[key] end # Returns the hash of defined options. # # @return [Hash] def option_set @options ||= {} end end # ContextOptions end # Riot riot-0.12.7/lib/riot/reporter.rb0000644000004100000410000000771412261222026016524 0ustar www-datawww-datamodule Riot # A Reporter decides how to output the result of a test. When a context is set to be executed, the # {Riot::Reporter#describe_context} method is called with the context that will be running; this remains # so until the next context is executed. After each {Riot::AssertionMacro#evaluate assertion is evaluated}, # {Riot::Reporter#report} is called with the description of the assertion and the resulting response. # # The general idea is that a sub-class of Reporter should be defined that knows specifically how to # output the reported results. In the sub-class, you simply need to implement a +pass+, +fail+, +error+, # and +results+ method. class Reporter # Count of successful assertions so far attr_accessor :passes # Count of failed assertions so far attr_accessor :failures # Count of errored assertions so far attr_accessor :errors # The context that is currently being reported on attr_accessor :current_context # Creates a new Reporter instance and initializes counts to zero def initialize(*args) @options = args.extract_options! @passes = @failures = @errors = 0 @current_context = Riot::RootContext.new end def new(*args, &block); self; end # Returns true if no failures or errors have been produced yet. # # @return [Boolean] def success? (@failures + @errors) == 0 end # Starts a timer, execute the provided block, then reports the results. Useful for timing context # execution(s). # # @param [lambda] &block the contexts to run def summarize(&block) started = Time.now yield ensure results(Time.now - started) end # Called when a new context is about to execute to set the state for this Reporter instance. # # @param [Riot::Context] context the context that is about to execute def describe_context(context) @current_context = context end # Called immediately after an assertion has been evaluated. From this method either +pass+, +fail+, # or +error+ will be called. # # @param [String] description the description of the assertion # @param [Array] response the evaluation response from the assertion def report(description, response) code, result = *response case code when :pass then @passes += 1 pass(description, result) when :fail then @failures += 1 message, line, file = *response[1..-1] fail(description, message, line, file) when :error, :setup_error, :context_error then @errors += 1 error(description, result) end end # Called if the assertion passed. # # @param [String] description the description of the assertion # @param [Array] result the evaluation response from the assertion def pass(description, result) raise "Implement this in a sub-class" end # Called if the assertion failed. # # @param [String] description the description of the assertion # @param [Array] response the evaluation response from the assertion def fail(description, message, line, file) raise "Implement this in a sub-class" end # Called if the assertion had an unexpected error. # # @param [String] description the description of the assertion # @param [Array] result the exception from the assertion def error(description, result) raise "Implement this in a sub-class" end # Called after all contexts have finished. This is where the final results can be output. # # @param [Number] time_taken number of seconds taken to run everything def results(time_taken) raise "Implement this in a sub-class" end end # Reporter end # Riot require 'riot/reporter/silent' require 'riot/reporter/io' require 'riot/reporter/story' require 'riot/reporter/dot_matrix' require 'riot/reporter/pretty_dot_matrix' riot-0.12.7/lib/riot.rb0000644000004100000410000001124712261222026014656 0ustar www-datawww-datarequire 'riot/reporter' require 'riot/middleware' require 'riot/context' require 'riot/situation' require 'riot/runnable' require 'riot/assertion' require 'riot/assertion_macro' # The namespace for all of Riot. module Riot # A helper for creating/defining root context instances. # # @param [String] description the description of this context # @param [Class] context_class the {Riot::Context} implementation to use # @param [lambda] &definition the context definition # @return [Context] the initialized {Riot::Context} def self.context(description, context_class = Context, &definition) (root_contexts << context_class.new(description, &definition)).last end # The set of {Riot::Context} instances that have no parent. # # @return [Array] instances of {Riot::Context} def self.root_contexts @root_contexts ||= [] end # How to run Riot itself. This should be called +at_exit+ unless you suggested - by calling {Riot.alone!} # that you want to call this method yourself. If no {Riot.reporter} is set, the # {Riot::StoryReporter default} will be used. # # You can change reporters by setting the manually via {Riot.reporter=} or by using one of: {Riot.dots}, # {Riot.silently!}, or {Riot.verbose}. # # @return [Riot::Reporter] the reporter that was used def self.run the_reporter = reporter.new(Riot.reporter_options) the_reporter.summarize do root_contexts.each { |ctx| ctx.run(the_reporter) } end unless root_contexts.empty? the_reporter end # Options that configure how Riot will run. # # @return [Hash] the options that tell Riot how to run def self.options @options ||= { :silent => false, :alone => false, :reporter => Riot::StoryReporter, :reporter_options => {:plain => false} } end # This means you don't want to see any output from Riot. A "quiet riot". def self.silently! Riot.options[:silent] = true end # Reponds to whether Riot is reporting silently. # # @return [Boolean] def self.silently? Riot.options[:silent] == true end # This means you don't want Riot to run tests for you. You will execute Riot.run manually. def self.alone! Riot.options[:alone] = true end # Responds to whether Riot will run +at_exit+ (false) or manually (true). # # @return [Boolean] def self.alone? Riot.options[:alone] == true end # Allows the reporter class to be changed. Do this before tests are started. # # @param [Class] reporter_class the Class that represents a {Riot::Reporter} def self.reporter=(reporter_class) Riot.options[:reporter] = reporter_class end # Returns the class for the reporter that is currently selected. If no reporter was explicitly selected, # {Riot::StoryReporter} will be used. # # @return [Class] the Class that represents a {Riot::Reporter} def self.reporter Riot.silently? ? Riot::SilentReporter : Riot.options[:reporter] end # Returns the options that will be passed to the Reporter when it is created. # # @return [Hash] the Hash of current options def self.reporter_options Riot.options[:reporter_options] end # @todo make this a flag that DotMatrix and Story respect and cause them to print errors/failures # Tells Riot to use {Riot::VerboseStoryReporter} for reporting def self.verbose Riot.reporter = Riot::VerboseStoryReporter end # Tells Riot to use {Riot::DotMatrixReporter} for reporting def self.dots Riot.reporter = Riot::DotMatrixReporter end # Tells Riot to use {Riot::PrettyDotMatrixReporter} for reporting def self.pretty_dots Riot.reporter = Riot::PrettyDotMatrixReporter end # Tells Riot to turn color off in the output def self.plain! Riot.reporter_options[:plain] = true end # Making sure to account for Riot being run as part of a larger rake task (or something similar). # If a child process exited with a failing status, probably don't want to run Riot tests; just exit # with the child status. at_exit do unless Riot.alone? status = $?.exitstatus unless ($?.nil? || $?.success?) exit(status || run.success?) end end end # Riot # A little bit of monkey-patch so we can have +context+ available anywhere. class Object # Defining +context+ in Object itself lets us define a root +context+ in any file. Any +context+ defined # within a +context+ is already handled by {Riot::Context#context}. # # @param (see Riot.context) # @return (see Riot.context) def context(description, context_class = Riot::Context, &definition) Riot.context(description, context_class, &definition) end alias_method :describe, :context end # Object class Array def extract_options! last.is_a?(::Hash) ? pop : {} end end riot-0.12.7/README.markdown0000644000004100000410000004511012261222026015303 0ustar www-datawww-data# Riot A fast, expressive, and contextual ruby unit testing framework. Protest the slow test. ## Installation gem install riot ## Usage [![Build Status](https://secure.travis-ci.org/thumblemonks/riot.png?branch=master)](http://travis-ci.org/thumblemonks/riot) In contrast to other popular Ruby testing frameworks such as Test::Unit, [Shoulda](http://github.com/thoughtbot/shoulda) and [RSpec](http://rspec.info/), Riot does not run a `setup` and `teardown` sequence before and after each test. This speeds up test execution quite a bit, but also changes how you write your tests. In general and in my opinion, you should avoid mutating any objects under test and if you use Riot you're pretty much going to have to. In Riot, tests reside in `contexts`. Within these, a `topic` object is defined through a `setup` block. The actual assertions are then made with an `asserts` or `denies` block. ```ruby context "An empty Array" do setup { Array.new } asserts("it is empty") { topic.empty? } denies("it has any elements") { topic.any? } end # An Array ``` As you can see, the setup block doesn't use any instance variables to save the object under test — rather, the return value of the block is used as the `topic`. This object can then be accessed in the assertions using the `topic` attribute. Furthermore, at their very basic level, assertions need only return a boolean. When using `asserts`, `true` indicates a pass while `false` indicates a fail; subsequently, when using `denies`, `true` indicates a failure whereas `false` indicates success. Of course, you can nest contexts as well; the `setup` blocks are executed outside-in; as in, the parents' setups are run before the current context allowing for a setup hierarchy. `teardown` blocks are run inside out; the current context's teardowns are run before any of its parents'. This is what you would expect from other frameworks as well. ```ruby context "An Array" do setup { Array.new } asserts("is empty") { topic.empty? } context "with one element" do setup { topic << "foo" } asserts("array is not empty") { !topic.empty? } asserts("returns the element on #first") { topic.first == "foo" } end end # An Array ``` By the way, you can put any kind of ruby object in your context description. Riot will call `to_s` on the actual value before it is used in a reporting context. This fact will become [useful later](http://thumblemonks.github.com/riot/hacking.html#context-middleware) ;) ## Assertions Well, how useful would Riot be if you could only return true/false from an assertion? Pretty useful, actually; but, we can make it more useful! No; that's not crazy. No it isn't. Yes; I'm sure. We can do this with assertion macros. You can think of these as special assertion modifiers that check the return value of the assertion block. Actually, it's not that you **can** think of them this way; you **should** think of them this way. Let's take this little for instance: ```ruby context "Yummy things" do setup { ["cookies", "donuts"] } asserts("#first") { topic.first }.equals("cookies") end # Yummy things ``` First, how's that for a readable test? Second, you should notice that the assertion block will return the `first` item from the `topic` (which is assumed to be `Enumerable` in this case); if it isn't `Enumerable`, then you have other problems. Since the first element in the array is "cookies", the assertion will pass. Yay! But wait, there's more. Riot is about helping you write faster and more readable tests. Notice any duplication in the example above (besides the value "cookies")? I do. How about that `first` notation in the assertion name and reference in the assertion block. Riot provides a shortcut which allows you to reference methods on the topic through the assertion name. Here's another way to write the same test: ```ruby context "Yummy things" do setup { ["cookies", "donuts"] } asserts(:first).equals("cookies") end # Yummy things ``` Now that's real yummy. Want some more? Perhaps you just want to test the topic itself — not a method or attribute of it. You could do this: ```ruby context "Yummy things" do setup { ["cookies", "donuts"] } asserts("topic") { topic }.size(2) end # Yummy things ``` But, as you can probably already guess, that's gross and redundant. To solve this, Riot provides the `asserts_topic` shortcut which is a helper that pretty much just does `asserts("topic") { topic }` for you. ```ruby context "Yummy things" do setup { ["cookies", "donuts"] } asserts_topic.size(2) end # Yummy things ``` Yep, more readable. ### Negative Assertions Way back in the first code example we saw a reference to `denies`; this is what is called the negative assertion. You could probably also call it a counter assertion, but I don't. You can use `denies` with any assertion macro that you can use `asserts` with; it's just that `denies` expects the assertion to fail for the test to pass. For instance: ```ruby context "My wallet" do setup do Wallet.new(1000) # That's 1000 cents, or $10USD yo end asserts(:enough_for_lunch?) denies(:enough_for_lunch?) end # My wallet ``` One of those will pass and the other will fail. If $10 is not enough for lunch the `denies` statement will pass; and then you should move to Chicago where it is enough (if only barely). ### Built-in Assertion Macros There are a bunch of built-in assertion macros for your everyday use. Be sure to [write your own](http://thumblemonks.github.com/riot/hacking.html#writing-assertion-macros) if these don't satisfy your every need. You will notice the two varying mechanisms for passing arguments into the macros: one is the conventional form of message passing (via actual arguments) and the other is derived from a provided block. If the macro expects one argument, you can use either form (but not both). If the macro accepts multiple arguments, the last argument you want to pass in can be provided via the block. The advantage of using the block is that its innards are evaluated against the same scope that the assertion was evaluated against. This means you can use the same helpers and instance variables in the macro block to generate an expected value (if you so desire). It's also useful if you have a fairly complex routine for generating the expected value. #### Equals Compares equality of the actual value to the expected value using the `==` operator ```ruby asserts.equals(Object) denies.equals(Object) asserts.equals { Object } denies.equals { Object } ``` #### Equivalent To Compares equivalence of actual value to the expected value using the `===` operator ```ruby asserts.equivalent_to(Object) denies.equivalent_to(Object) asserts.equivalent_to { Object } denies.equivalent_to { Object } ``` #### Assigns Checks that the actual value has an instance variable defined within it's scope. You can also validate the value of that variable. Very much mimicing the `assigns` found in Rails-ish tests from way back in form, function, and need. ```ruby asserts("a person") { Person.new }.assigns(:email) denies("a person") { Person.new }.assigns(:email) asserts("a person") { Person.new(:email => "a@b.com") }.assigns(:email, "a@b.com") denies("a person") { Person.new(:email => "a@b.com") }.assigns(:email, "a@b.com") asserts.assigns { :email } denies.assigns { :email } asserts.assigns(:email) { "a@b.com" } denies.assigns(:email) { "a@b.com" } ``` #### Nil Simply checks the actual value for its nil-ness. Expects no arguments. ```ruby asserts.nil denies.nil ``` #### Matches Compares the actual value to a provided regular expression ```ruby asserts.matches(%r{Regex}) denies.matches(%r{Regex}) asserts.matches { /Regex/ } denies.matches { /Regex/ } ``` #### Raises Validates the type of exception raised from the assertion block. Optionally, you can give it the message you expected in the form of a literal string or even a portion of it. ```ruby asserts.raises(ExceptionClass) denies.raises(ExceptionClass) asserts.raises(ExceptionClass, "Expected message") denies.raises(ExceptionClass, "Expected message") asserts.raises(ExceptionClass) { "ted mess" } denies.raises(ExceptionClass) { "ted mess" } ``` #### Kind Of Validates the type of object returned from the assertion block ```ruby asserts.kind_of(Class) denies.kind_of(Class) asserts.kind_of { Class } denies.kind_of { Class } ``` #### Responds To Checks that the actual object `respond_to?` to a particular message ```ruby asserts.respond_to(:foo) denies.respond_to(:foo) asserts.respond_to { "foo" } denies.respond_to { "foo" } asserts.responds_to("foo") denies.responds_to("foo") asserts.responds_to { :foo } denies.responds_to { :foo } ``` #### Includes Checks for the existence of: a character or sequence of characters in a string, an element in an array, or a key in a hash. ```ruby asserts("this string") { "barbie q" }.includes("foo") denies("this string") { "barbie q" }.includes("foo") asserts("this array") { [1,2,3] }.includes(2) denies("this array") { [1,2,3] }.includes(2) asserts("this hash") { {:key1 => "foo"} }.includes(:key2) denies("this hash") { {:key1 => "foo"} }.includes(:key2) asserts.includes { "foo" } denies.includes { "foo" } asserts.includes { 2 } denies.includes { 2 } asserts.includes { :key } denies.includes { :key } ``` #### Size Compares the size of the actual object to the number you provide. Works with anything that responds to `size(Numeric)` (strings, arrays, hashes, etc). ```ruby asserts.size(Numeric) denies.size(Numeric) asserts.size { Numeric } denies.size { Numeric } ``` #### Empty Checks the result of calling `empty?` on the actual value. Expects no arguments. ```ruby asserts.empty denies.empty ``` #### Same Elements Compares actual to expected to see if they contain the same elements. Uses `Set` under-the-hood, just so you know. ```ruby asserts.same_elements(Array) denies.same_elements(Array) asserts.same_elements { Array } denies.same_elements { Array } ``` ### Setups, Hookups, and Helpers We're not even close to done yet; there's a lot more cool stuff for you to know about. You know about `setup` already; but you may not know that you can call `setup` multiple times within a Context. Well, you can. They run in the order you write them (top-down) and the result of a prior `setup` will be the `topic` for the next setup. In this way you **could** chain together some partitioned setup criteria without ever explicitly setting a variable (instance or local). ```ruby context "A cheesey order" do setup { Cheese.create!(:name => "Blue") } setup { Order.create!(:cheese => topic, :purchase_order => "123-abc") } asserts_topic.kind_of(Order) # I love tests that are readable end # A cheesey order ``` This notion about a prior `setup` being the `topic` for a latter `setup` is true even when the `setup` is called from a parent Context. More than likely, however, you'll want to modify something about the topic without changing what the topic for the context is. To do this, Riot provides the `hookup` block, which is just like a `setup` block except that `hookup` will always return the `topic` that was provided to it. It's kind of like calling `Object#tap`. Here's a for-instance: ```ruby context "A Person" do setup { Person.new(:name => "Master Blasterr") } denies(:valid?) # :( context "with valid email" do hookup { topic.email = "master@blast.err" } asserts(:valid?) # Yay! end # with valid email end # A complex thing ``` If the point didn't smack you in the face there, think about using `setup` instead of `hookup` in the sub-context. Had you written that as a `setup` block, you'd have to return `topic` after setting the email address, or else the new topic would be the actual email address; and you probably don't want to actually be calling `"master@blast.err".valid?` in the assertion. You can also call `hookup` as many times as you like; the great part is that the `topic` never changes. #### Helpers You remember how you used to — or currently do — create instance variables to hold some data that you're going to use in your tests? Well, Riot allows you to still do that yucky stuff, but would rather you use a helper to encapsulate it. For instance, you could do this: ```ruby context "A greedy monkey" do setup do @a_ripe_banana = Banana.new(:ripe => true) Monkey.new end hookup { topic.takes(@a_ripe_banana) } asserts(:bananas).size(1) end # A greedy monkey ``` Or, you could do this ```ruby context "A greedy monkey" do helper(:a_ripe_banana) { Banana.new(:ripe => true) } setup { Monkey.new } hookup { topic.takes(a_ripe_banana) } asserts(:bananas).size(1) end # A greedy monkey ``` "So! What's the difference?", you ask. Nothing really. It's all aesthetic; but, it's a better aesthetic for a couple of reasons. Let me tell you why: 1. Helpers are good ways to encapsulate related setup data and give that data namespace 2. The act of setting up data does not clutter up your setups or assertions 3. I'll argue that it makes the code more readable; ex. how do you verbalize to your friends `@a_banana` and `a_banana`. In the former, I probably say "at a banana" and think "Why do I sound like a muppet when I talk?". 3. Being that helpers are blocks, you can actually pass arguments to them What's that about (4)? Yes, helpers are really just over-glorified methods, which means you can pass arguments to them. Which means you can build factories with them. Which means those factories can go away when the context is no longer used and they're no longer cluttering up your object space. You want another for instance, eh? ```ruby context "A greedy monkey" do helper(:make_a_banana) do |color| Banana.new(:color => color) end setup { Monkey.new } hookup do topic.takes(make_a_banana("green")) topic.takes(make_a_banana("blue")) end asserts(:bananas).size(2) asserts("green bananas") { topic.bananas.green }.size(1) asserts("blue bananas") { topic.bananas.blue }.size(1) end # A greedy monkey ``` Or you could `make_many_bananas` or whatever. There are also lots of clever ways to get helpers included into a context which you will hopefully see when you read up on Context Middleware and look through the Recipes. Riot Rails makes liberal use of helpers when [setting up a context](http://github.com/thumblemonks/riot-rails/master/lib/riot/action_controller/context_middleware.rb) to test controllers. Again, you define as many helpers as you like; you can also replace existing helpers by simply defining a helper with the same name (*that's because they're just methods defined within the context instance ... shhh*). ### Running Riot Running your Riot tests is pretty simple. You can put your test files wherever you want, but it's generally a good idea to put them in a "test" directory. You can run individual test files using the normal ruby command: ```plain ruby test/units/monkey_test.rb # or ruby -Itest test/units/monkey_test.rb ``` I like the latter and use it often. It means the test directory is loaded into the load path, which means I don't have to be explicit about where to find my `teststrap.rb` file (which you might have named `test_helper.rb` in other projects even though it's a silly name). In your teststrap file you'll put all your common setup; maybe even including your Riot hacks. An out-of-the-box teststrap might look like this: ```ruby require 'rubygems' require '' require 'riot' ``` Of course, you probably want to use rake to run your tests. Here's a basic Rakefile that will find our tests in the test directory or its subdirectories if the filename ends in `_test.rb`: ```ruby require 'rubygems' require 'rake' require 'rake/testtask' desc "Run all our tests" task :test do Rake::TestTask.new do |t| t.libs << "test" t.pattern = "test/**/*_test.rb" t.verbose = false end end task :default => :test ``` And then on the command line you simply run: ```plain rake # or rake test ``` ### Mocking Mocking seems to be all the rage this decade. I try very hard to avoid it altogether through judicious use of anonymous classes, but sometimes you just need to mock. For Riot, [RR](http://github.com/btakita/rr) seemed to fit the bill nicely because it's: * Lightweight * Laid back * Test framework agnostic and easy to integrate with * Starts and ends with TWO R's! That second to last point needs to be stressed a bit more. RR's default behavior is to not give a crap about what test framework you use. I can already hear you thinking, *"But wait, aren't you tying Riot to a mock framework?"* Well, not really. Riot is mock framework agnostic; it'll work with any framework that can be worked with. Riot does not implicitly require in any RR support; you have to do that in your test-strapping. However, there are a number of things you expect from a test framework when mocking is involved. Namely, if a mock expectation fails you want the context or assertion to fail, too. Additionally, you don't want to have to ask the mocking framework to validate itself for each assertion; you want Riot to do that for you. And some other things. So, Riot does most of the tedious mock-lifting for you and it suggests you use RR, but doesn't require it. But enough of this hemming and hawing. What's it look like?! In your `teststrap.rb` you need to require in `riot/rr`: ```ruby # I'm teststrap.rb require 'rubygems' require 'riot/rr' ``` Then, in your tests, you use standard RR syntax for all of your mocking needs: ```ruby require 'teststrap.rb' context "A nice Person" do setup do Nice::Person.new end should("find a nice thing to say") do mock(topic).make_network_request { "Nice haircut" } topic.say_something_nice end.equals("Nice haircut") end # A nice Person ``` So, if `#say_something_nice` never calls `#make_network_request`, that assertion will fail for that reason first. If it does call `#make_network_request`, but for some reason "Nice haircut" is not returned, the tests will fail for that reason instead. It's like catching two birds with one test. This is not an RR guide so you need to get familiar with it's syntax. Needless to say, if you require it in it's methods are available within any assertion, setup, teardown, hookup, and helper. ## Contributing Riot is slowly solidifying its internal and external API. That being said, we would love to hear any thoughts and ideas, and bug reports are always welcome. We hang out in `#riot` on `irc.freenode.net`. Source code is hosted on [GitHub](http://github.com), and can be fetched with [Git](http://git-scm.com) by running: ```plain git clone git://github.com/thumblemonks/riot.git ``` If you want to make changes, please feel free to do so. The best process is to fork, fix, and send a pull request. ## License Riot is released under the MIT license. See [MIT LICENSE](https://github.com/thumblemonks/riot/blob/master/MIT-LICENSE). riot-0.12.7/metadata.yml0000644000004100000410000001477212261222026015117 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: riot version: !ruby/object:Gem::Version version: 0.12.7 prerelease: platform: ruby authors: - Justin 'Gus' Knowlden autorequire: bindir: bin cert_chain: [] date: 2013-10-18 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: rr requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' description: An extremely fast, expressive, and context-driven unit-testing framework. A replacement for all other testing frameworks. Protest the slow test. email: gus@gusg.us executables: [] extensions: [] extra_rdoc_files: [] files: - .gitignore - .travis.yml - .yardopts - CHANGELOG - Gemfile - MIT-LICENSE - README.markdown - Rakefile - lib/riot.rb - lib/riot/assertion.rb - lib/riot/assertion_macro.rb - lib/riot/assertion_macros/any.rb - lib/riot/assertion_macros/assigns.rb - lib/riot/assertion_macros/empty.rb - lib/riot/assertion_macros/equals.rb - lib/riot/assertion_macros/equivalent_to.rb - lib/riot/assertion_macros/exists.rb - lib/riot/assertion_macros/includes.rb - lib/riot/assertion_macros/kind_of.rb - lib/riot/assertion_macros/matches.rb - lib/riot/assertion_macros/nil.rb - lib/riot/assertion_macros/raises.rb - lib/riot/assertion_macros/raises_kind_of.rb - lib/riot/assertion_macros/respond_to.rb - lib/riot/assertion_macros/same_elements.rb - lib/riot/assertion_macros/size.rb - lib/riot/context.rb - lib/riot/context_helpers.rb - lib/riot/context_options.rb - lib/riot/message.rb - lib/riot/middleware.rb - lib/riot/reporter.rb - lib/riot/reporter/dot_matrix.rb - lib/riot/reporter/io.rb - lib/riot/reporter/pretty_dot_matrix.rb - lib/riot/reporter/silent.rb - lib/riot/reporter/story.rb - lib/riot/rr.rb - lib/riot/runnable.rb - lib/riot/situation.rb - lib/riot/version.rb - riot.gemspec - test/benchmark/message_concatenation.rb - test/benchmark/riot_vs_minitest.rb - test/benchmark/same_elements_vs_set.rb - test/benchmark/simple_context_and_assertions.rb - test/core/assertion_macros/any_test.rb - test/core/assertion_macros/assigns_test.rb - test/core/assertion_macros/empty_test.rb - test/core/assertion_macros/equals_test.rb - test/core/assertion_macros/equivalent_to_test.rb - test/core/assertion_macros/exists_test.rb - test/core/assertion_macros/includes_test.rb - test/core/assertion_macros/kind_of_test.rb - test/core/assertion_macros/matches_test.rb - test/core/assertion_macros/nil_test.rb - test/core/assertion_macros/raises_kind_of_test.rb - test/core/assertion_macros/raises_test.rb - test/core/assertion_macros/respond_to_test.rb - test/core/assertion_macros/same_elements_test.rb - test/core/assertion_macros/size_test.rb - test/core/context/asserts_topic_test.rb - test/core/context/asserts_with_arguments_test.rb - test/core/context/context_test.rb - test/core/context/context_with_options_test.rb - test/core/context/denies_with_arguments_test.rb - test/core/context/deny_test.rb - test/core/context/helper_test.rb - test/core/context/hookup_test.rb - test/core/context/nested_contexts_test.rb - test/core/context/premium_setup_test.rb - test/core/context/should_test.rb - test/core/context/using_describe_in_a_test.rb - test/core/middleware/chained_context_middleware_test.rb - test/core/middleware/context_middleware_test.rb - test/core/reports/basic_reporter_test.rb - test/core/reports/dot_matrix_reporter_test.rb - test/core/reports/story_reporter_test.rb - test/core/runnable/assertion_macro_test.rb - test/core/runnable/assertion_test.rb - test/core/runnable/erroring_gracefully_test.rb - test/core/runnable/message_test.rb - test/core/runnable/negative_assertion_test.rb - test/core/runnable/setup_test.rb - test/core/runnable/situation_test.rb - test/core/runnable/teardown_test.rb - test/extensions/rrriot_test.rb - test/teststrap.rb homepage: http://github.com/thumblemonks/riot licenses: [] post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 1.8.25 signing_key: specification_version: 3 summary: An extremely fast, expressive, and context-driven unit-testing framework. Protest the slow test. test_files: - test/benchmark/message_concatenation.rb - test/benchmark/riot_vs_minitest.rb - test/benchmark/same_elements_vs_set.rb - test/benchmark/simple_context_and_assertions.rb - test/core/assertion_macros/any_test.rb - test/core/assertion_macros/assigns_test.rb - test/core/assertion_macros/empty_test.rb - test/core/assertion_macros/equals_test.rb - test/core/assertion_macros/equivalent_to_test.rb - test/core/assertion_macros/exists_test.rb - test/core/assertion_macros/includes_test.rb - test/core/assertion_macros/kind_of_test.rb - test/core/assertion_macros/matches_test.rb - test/core/assertion_macros/nil_test.rb - test/core/assertion_macros/raises_kind_of_test.rb - test/core/assertion_macros/raises_test.rb - test/core/assertion_macros/respond_to_test.rb - test/core/assertion_macros/same_elements_test.rb - test/core/assertion_macros/size_test.rb - test/core/context/asserts_topic_test.rb - test/core/context/asserts_with_arguments_test.rb - test/core/context/context_test.rb - test/core/context/context_with_options_test.rb - test/core/context/denies_with_arguments_test.rb - test/core/context/deny_test.rb - test/core/context/helper_test.rb - test/core/context/hookup_test.rb - test/core/context/nested_contexts_test.rb - test/core/context/premium_setup_test.rb - test/core/context/should_test.rb - test/core/context/using_describe_in_a_test.rb - test/core/middleware/chained_context_middleware_test.rb - test/core/middleware/context_middleware_test.rb - test/core/reports/basic_reporter_test.rb - test/core/reports/dot_matrix_reporter_test.rb - test/core/reports/story_reporter_test.rb - test/core/runnable/assertion_macro_test.rb - test/core/runnable/assertion_test.rb - test/core/runnable/erroring_gracefully_test.rb - test/core/runnable/message_test.rb - test/core/runnable/negative_assertion_test.rb - test/core/runnable/setup_test.rb - test/core/runnable/situation_test.rb - test/core/runnable/teardown_test.rb - test/extensions/rrriot_test.rb - test/teststrap.rb riot-0.12.7/test/0000755000004100000410000000000012261222026013560 5ustar www-datawww-datariot-0.12.7/test/core/0000755000004100000410000000000012261222026014510 5ustar www-datawww-datariot-0.12.7/test/core/middleware/0000755000004100000410000000000012261222026016625 5ustar www-datawww-datariot-0.12.7/test/core/middleware/context_middleware_test.rb0000644000004100000410000000641712261222026024102 0ustar www-datawww-datarequire 'teststrap' context "ContextMiddleware" do setup { Riot::ContextMiddleware.new("") } teardown { Riot::Context.middlewares.clear } asserts("#call on the base class") do topic.call("Foo") end.raises(RuntimeError, "You should implement call yourself") context "registration" do setup { Class.new(Riot::ContextMiddleware) { register } } asserts("registered middlewares list") { Riot::Context.middlewares }.size(1) asserts("registered middleware") { Riot::Context.middlewares.first }.kind_of(Class) end # registration context "that is not meant to be used" do hookup do Class.new(Riot::ContextMiddleware) do register # def handle?(context) context.description == "Bar"; end def call(context) context.setup { "fooberries" } if context.description == "Bar" middleware.call(context) end end end setup do Riot::Context.new("Foo") { asserts_topic.nil }.run(MockReporter.new) end asserts("tests passed") { topic.passes }.equals(1) end # that is not meant to be used context "that is meant to be used" do hookup do Class.new(Riot::ContextMiddleware) do register # def handle?(context); true; end def call(context) context.setup { "fooberries" } middleware.call(context) end end end setup do Riot::Context.new("Foo") { asserts_topic.equals("fooberries") }.run(MockReporter.new) end asserts("tests passed") { topic.passes }.equals(1) end # that is meant to be used context "applied in multiples" do hookup do Class.new(Riot::ContextMiddleware) do register def call(context) context.setup { topic + "berries" } middleware.call(context) end end end hookup do Class.new(Riot::ContextMiddleware) do register def call(context) context.setup { "foo" } middleware.call(context) end end end setup do Riot::Context.new("Foo") { asserts_topic.equals("fooberries") }.run(MockReporter.new) end asserts("tests passed") { topic.passes }.equals(1) end # that are not exclusive context "has access to options after context setup" do hookup do Class.new(Riot::ContextMiddleware) do register def call(context) middleware.call(context) context.setup { "fooberries" } if context.option(:foo) == "bar" end end end setup do Riot::Context.new("Foo") do set :foo, "bar" asserts_topic.equals("fooberries") end.run(MockReporter.new) end asserts("tests passed") { topic.passes }.equals(1) end # has access to options after context setup context "that errors while preparing" do hookup do Class.new(Riot::ContextMiddleware) do register def call(context) raise Exception.new("Banana pants") end end end setup do Riot::Context.new("Foo") { asserts_topic.nil }.run(MockReporter.new) end asserts("tests passed") { topic.passes }.equals(0) asserts("tests failed") { topic.failures }.equals(0) asserts("tests errored") { topic.errors }.equals(1) end # that is not meant to be used end # ContextMiddleware riot-0.12.7/test/core/middleware/chained_context_middleware_test.rb0000644000004100000410000000235712261222026025554 0ustar www-datawww-datarequire 'teststrap' context "Chaining ContextMiddleware" do teardown { Riot::Context.middlewares.clear } context("when middleware halts the call chain") do hookup do Class.new(Riot::ContextMiddleware) do register def initialize(middleware); end def call(context) "whoops"; end end end setup do situation = Riot::Situation.new Riot::Context.new("Foo") do setup { "foo" } end.local_run(MockReporter.new, situation) situation end asserts("situation topic") { topic.topic }.nil end # when middleware halts the call chain context("when middleware continues the call chain") do hookup do Class.new(Riot::ContextMiddleware) do register def call(context) context.setup { ["foo"] } middleware.call(context) context.hookup { topic << "baz" } end end end setup do situation = Riot::Situation.new Riot::Context.new("Foo") do hookup { topic << "bar" } end.local_run(MockReporter.new, situation) situation end asserts("situation topic") { topic.topic }.equals(%w[foo bar baz]) end # when middleware halts the call chain end # Chaining ContextMiddleware riot-0.12.7/test/core/context/0000755000004100000410000000000012261222026016174 5ustar www-datawww-datariot-0.12.7/test/core/context/nested_contexts_test.rb0000644000004100000410000000222712261222026022774 0ustar www-datawww-datarequire 'teststrap' context "Nesting a context" do setup do a_context = Riot::Context.new("foobar") do asserts("passing") { true } context "bazboo" do asserts("passing") { true } asserts("failing") { false } asserts("erroring") { raise Exception } end end a_context.run(MockReporter.new) end asserts("one passed test") { topic.passes == 2 } asserts("one failed test") { topic.failures == 1 } asserts("one errored test") { topic.errors == 1 } context "with setups" do setup do a_context = Riot::Context.new("foobar") do setup { "foo" } context "bazboo" do setup { topic + "bar" } asserts("passing") { topic == "foobar" } end end a_context.run(MockReporter.new) end asserts("parent setups are called") { topic.passes == 1 } end # with setups end # Nesting a context context "A context with nested descriptions as classes" do setup { Riot::Context.new(String) {}.context(Hash) {} } asserts(:description).equals { Hash } asserts(:detailed_description).equals("String Hash") end # A context with nested descriptions as classes riot-0.12.7/test/core/context/context_test.rb0000644000004100000410000000206412261222026021246 0ustar www-datawww-datarequire 'teststrap' context "Reporting a context" do setup do a_context = Riot::Context.new("foobar") do asserts("passing") { true } asserts("failing") { false } asserts("erroring") { raise Exception } end a_context.run(MockReporter.new) end asserts("one passed test") { topic.passes == 1 } asserts("one failed test") { topic.failures == 1 } asserts("one errored test") { topic.errors == 1 } end # Reporting a context context "Defining a context with multiple setups" do setup do @a_context = Riot::Context.new("foobar") do setup { "foo" } setup { topic + "bar" } asserts("blah") { topic == "foobar" } end @a_context.run(MockReporter.new) end asserts("has setups") { @a_context.setups.size }.equals(2) asserts("all tests pass") { topic.passes == 1 } end # Defining a context with multiple setups context "Making a new context" do asserts("RootContext is used if nil parent is provided") do Riot::Context.new("hello", nil) {}.parent end.kind_of(Riot::RootContext) end # Making a context riot-0.12.7/test/core/context/context_with_options_test.rb0000644000004100000410000000172612261222026024060 0ustar www-datawww-datarequire 'teststrap' context "Context with options" do setup do Riot::Context.new("Foo") do set :foo, "bar" set "bar", 2 end end asserts_topic.responds_to(:option) asserts("option :foo") { topic.option(:foo) }.equals("bar") asserts("option \"foo\"") { topic.option("foo") }.nil asserts("option \"bar\"") { topic.option("bar") }.equals(2) context "and with a nested context" do setup do Riot::Context.new("Foo", topic) do set :goo, "car" set "car", 3 end end asserts_topic.responds_to(:option) asserts("option :foo") { topic.option(:foo) }.equals("bar") asserts("option \"bar\"") { topic.option("bar") }.equals(2) asserts("option :goo") { topic.option(:goo) }.equals("car") asserts("option \"car\"") { topic.option("car") }.equals(3) asserts("option :goo on parent") do topic.parent.option(:goo) end.equals(nil) end # and with a nested context end # Context with options riot-0.12.7/test/core/context/denies_with_arguments_test.rb0000644000004100000410000000141012261222026024143 0ustar www-datawww-datarequire 'teststrap' context "a negative assertion made with arguments" do setup do Riot::Context.new("foo") {}.denies(:[], 0) end should("pass its argument to send, with the first argument as method name") do (situation = Riot::Situation.new).instance_variable_set(:@_topic, [1, 2]) topic.equals(1).run(situation).first end.equals(:fail) end # assertion made with arguments context "a negative assertion made with arguments" do setup do Riot::Context.new("foo") {}.should_not(:[], 0) end should("pass its argument to send, with the first argument as method name") do (situation = Riot::Situation.new).instance_variable_set(:@_topic, [1, 2]) topic.equals(1).run(situation).first end.equals(:fail) end # assertion made with arguments riot-0.12.7/test/core/context/deny_test.rb0000644000004100000410000000267612261222026020532 0ustar www-datawww-datarequire 'teststrap' context "Using denies" do helper(:denial_context) do |actual| report = Riot::Context.new("Apple Jackie") do denies("with false") { actual } end.run(MockReporter.new) [report.passes, report.failures, report.errors] end # denial_context asserts("result when returning false from the assertion block") do denial_context(false) end.equals([1,0,0]) asserts("result when returning true from the assertion block") do denial_context(true) end.equals([0,1,0]) asserts("result when assertion block has an exception") do Riot::Context.new("Apple Jackie") do denies("with false") { raise Exception } end.run(MockReporter.new).errors end.equals(1) end # Using denies context "Using should_not" do helper(:denial_context) do |actual| report = Riot::Context.new("Apple Jackie") do should_not("with false") { actual } end.run(MockReporter.new) [report.passes, report.failures, report.errors] end # denial_context asserts("result when returning false from the assertion block") do denial_context(false) end.equals([1,0,0]) asserts("result when returning true from the assertion block") do denial_context(true) end.equals([0,1,0]) asserts("result when assertion block has an exception") do Riot::Context.new("Apple Jackie") do should_not("with false") { raise Exception } end.run(MockReporter.new).errors end.equals(1) end # Using should_not riot-0.12.7/test/core/context/using_describe_in_a_test.rb0000644000004100000410000000154412261222026023537 0ustar www-datawww-datarequire 'teststrap' context "The describe alias" do setup do Riot::Context.new("Foo") {} end asserts("any ol' object") { Object.new }.responds_to(:describe) asserts_topic.responds_to :describe end # The describe alias describe "This describe context" do setup { "another thing is my" } asserts_topic.kind_of(String) end # This describe context context "Using a describe sub-context" do setup do Riot::Context.new("Foo") do describe "using describe" do setup { "another thing is my" } asserts_topic.kind_of(String) end end.run(Riot::SilentReporter.new) end asserts("current context description") do topic.current_context.detailed_description end.equals("Foo using describe") asserts(:passes).equals(1) asserts(:failures).equals(0) asserts(:errors).equals(0) end # Using a describe sub-context riot-0.12.7/test/core/context/helper_test.rb0000644000004100000410000000045112261222026021037 0ustar www-datawww-datarequire 'teststrap' context "A context with a helper" do setup { "foo" } helper(:upcase) { topic.upcase } helper(:append) {|str| topic + str } asserts("executing the helper") { upcase }.equals("FOO") asserts("calling a helper with an argument") { append("bar") }.equals("foobar") end riot-0.12.7/test/core/context/hookup_test.rb0000644000004100000410000000052112261222026021063 0ustar www-datawww-datarequire 'teststrap' context "Using a hookup" do setup do situation = Riot::Situation.new a_context = Riot::Context.new("foobar") {} a_context.setup { "I'm a string" }.run(situation) a_context.hookup { topic.size }.run(situation) situation.topic end asserts_topic.equals("I'm a string") end # Using a hookup riot-0.12.7/test/core/context/should_test.rb0000644000004100000410000000066312261222026021063 0ustar www-datawww-datarequire 'teststrap' context "Using should" do setup do a_context = Riot::Context.new("foobar") do should("pass") { true } should("fail") { false } should("error") { raise Exception } end a_context.run(MockReporter.new) end asserts("one passed test") { topic.passes == 1 } asserts("one failed test") { topic.failures == 1 } asserts("one errored test") { topic.errors == 1 } end # Using should riot-0.12.7/test/core/context/asserts_with_arguments_test.rb0000644000004100000410000000132112261222026024361 0ustar www-datawww-datarequire 'teststrap' context "an assertion made with arguments" do setup do Riot::Context.new("foo") {}.asserts(:[], 0) end should("pass its argument to send, with the first argument as method name") do (situation = Riot::Situation.new).instance_variable_set(:@_topic, [1, 2]) topic.equals(1).run(situation).first end.equals(:pass) end # assertion made with arguments context "a should made with arguments" do setup do Riot::Context.new("foo") {}.should(:[], 0) end should("pass its argument to send, with the first argument as method name") do (situation = Riot::Situation.new).instance_variable_set(:@_topic, [1, 2]) topic.equals(1).run(situation).first end.equals(:pass) end riot-0.12.7/test/core/context/asserts_topic_test.rb0000644000004100000410000000250312261222026022442 0ustar www-datawww-datarequire 'teststrap' context "The asserts_topic shortcut" do setup do Riot::Context.new("foo") {}.asserts_topic end should("return an Assertion") { topic }.kind_of(Riot::Assertion) should("return the actual topic as the result of evaling the assertion") do (situation = Riot::Situation.new).instance_variable_set(:@_topic, "bar") topic.equals("bar").run(situation) end.equals([:pass, %Q{is equal to "bar"}]) asserts(:to_s).equals("asserts that it") context "with an explicit description" do setup { Riot::Context.new("foo") {}.asserts_topic("get some") } asserts(:to_s).equals("asserts get some") end end # The asserts_topic shortcut context "The denies_topic shortcut" do setup do Riot::Context.new("foo") {}.denies_topic end should("return an Assertion") { topic }.kind_of(Riot::Assertion) should("return the actual topic as the result of evaling the assertion") do (situation = Riot::Situation.new).instance_variable_set(:@_topic, "bar") topic.equals("not bar").run(situation) end.equals([:pass, %Q{is equal to "not bar" when it is "bar"}]) asserts(:to_s).equals("denies that it") context "with an explicit description" do setup { Riot::Context.new("foo") {}.denies_topic("get some") } asserts(:to_s).equals("denies get some") end end # The denies_topic shortcut riot-0.12.7/test/core/context/premium_setup_test.rb0000644000004100000410000000074212261222026022461 0ustar www-datawww-datarequire 'teststrap' class SingletonArray def self.<<(value); values << value; end def self.values; @@values ||= []; end end context "A context with premium_setup" do setup do Riot::Context.new("Foo") do setup { SingletonArray << "baz" } setup(true) { SingletonArray << "bar" } setup(true) { SingletonArray << "foo" } end.run(MockReporter.new) end asserts("order of setups ensures topic") { SingletonArray.values }.equals(%w[foo bar baz]) end riot-0.12.7/test/core/runnable/0000755000004100000410000000000012261222026016316 5ustar www-datawww-datariot-0.12.7/test/core/runnable/erroring_gracefully_test.rb0000644000004100000410000000243612261222026023753 0ustar www-datawww-datarequire 'teststrap' context "Executing setup with an error" do setup do Riot::Setup.new { raise "Error in setup" }.run(Riot::Situation.new) end asserts("result") { topic[0] }.equals(:setup_error) asserts("result object") { topic[1] }.kind_of(Exception) asserts("error message") { topic[1].message }.equals("Error in setup") end # Executing setup with an error context "Executing a context" do context "that errors during setup" do setup do Riot::Context.new("A") { setup { raise "Whoopsie!" } # error asserts("foo") { true } # success asserts("bar") { false } # failure }.run(Riot::SilentReporter.new) end asserts(:errors).equals(1) asserts(:failures).equals(0) asserts(:passes).equals(0) end # that errors during setup context "that errors in a parent setup" do setup do Riot::Context.new("A") { setup { raise "Whoopsie!" } # error context "B" do asserts("foo") { true } # success asserts("bar") { false } # failure end }.run(Riot::SilentReporter.new) end asserts(:errors).equals(2) # Same setup fails twice asserts(:failures).equals(0) asserts(:passes).equals(0) end # that errors in a parent setup end # Executing a cotext riot-0.12.7/test/core/runnable/negative_assertion_test.rb0000644000004100000410000000243612261222026023600 0ustar www-datawww-datarequire 'teststrap' context "A negative assertion test" do helper(:negative_assertion) do |definition| Riot::Assertion.new("foo", true) { definition } end asserts("response when evaluated with false result") do negative_assertion(false).run(Riot::Situation.new) end.equals([:pass, ""]) asserts("response when evaluated with nil result") do negative_assertion(false).run(Riot::Situation.new) end.equals([:pass, ""]) asserts("response when evaluated with true result") do negative_assertion(true).run(Riot::Situation.new) end.equals([:fail, "Expected non-true but got true instead", nil, nil]) asserts("response when evaluated with \"bar\" result") do negative_assertion("bar").run(Riot::Situation.new) end.equals([:fail, "Expected non-true but got \"bar\" instead", nil, nil]) asserts("response when evaluated with 0 result") do negative_assertion(0).run(Riot::Situation.new) end.equals([:fail, "Expected non-true but got 0 instead", nil, nil]) helper(:big_exception) { @exception ||= Exception.new("blah") } asserts("response when evaluation errors") do exception = big_exception # :\ Riot::Assertion.new("foo", true) { raise exception }.run(Riot::Situation.new) end.equals { [:error, big_exception] } end # A negative assertion test riot-0.12.7/test/core/runnable/setup_test.rb0000644000004100000410000000060212261222026021040 0ustar www-datawww-datarequire 'teststrap' context "A setup block" do setup do Riot::Setup.new { "fooberries" } end asserts("topic is set for situation when run") do situation = Riot::Situation.new topic.run(situation) situation.topic == "fooberries" end asserts(":setup is returned from calling run") do topic.run(Riot::Situation.new) == [:setup] end end # A setup block riot-0.12.7/test/core/runnable/message_test.rb0000644000004100000410000000263112261222026021330 0ustar www-datawww-datarequire 'teststrap' context "A message object" do asserts("blank message on initialization") { Riot::Message.new.to_s }.equals("") asserts("opening phrase has inspected values") do Riot::Message.new("bar", nil, {:a => 2}).to_s end.equals(%q["bar", nil, {:a=>2}]) context "receiving calls for unbound methods" do asserts("message") do Riot::Message.new.bar.to_s end.equals(%q[bar]) asserts("message with an arguments") do Riot::Message.new("Foo").bar("baz").to_s end.equals(%q["Foo" bar "baz"]) asserts("message with multiple arguments") do Riot::Message.new("Foo").bar("baz", "boo", [1,2,3]).to_s end.equals(%q{"Foo" bar "baz", "boo", [1, 2, 3]}) asserts("in a long chain with underscored words") do Riot::Message.new.bar.baz.your_mom.to_s end.equals(%q[bar baz your mom]) end # unbound methods asserts("#comma with a message") { Riot::Message.new.comma("and").to_s }.equals(", and") asserts("#but") { Riot::Message.new.but.to_s }.equals(", but") asserts("#but with message") { Riot::Message.new("Foo").but("a").to_s }.equals(%q["Foo", but "a"]) asserts("#not") { Riot::Message.new.not.to_s }.equals(", not") asserts("#not with message") { Riot::Message.new("Foo").not("a").to_s }.equals(%q["Foo", not "a"]) asserts("calling with inspect") do Riot::Message.new.happy_nappy.inspect.to_s end.equals("happy nappy") end # A message object riot-0.12.7/test/core/runnable/assertion_macro_test.rb0000644000004100000410000000224612261222026023076 0ustar www-datawww-datarequire 'teststrap' context "An AssertionMacro instance" do setup { Riot::AssertionMacro.new } asserts_topic.responds_to(:new_message) asserts_topic.responds_to(:expected_message) asserts_topic.responds_to(:should_have_message) asserts_topic.responds_to(:line) asserts_topic.responds_to(:line=) asserts_topic.responds_to(:file) asserts_topic.responds_to(:file=) context "receiving #new_message" do setup { topic.new_message("hope") } asserts_topic.kind_of(Riot::Message) asserts(:to_s).equals(%q["hope"]) end context "receiving #should_have_message" do setup { topic.should_have_message("hope") } asserts_topic.kind_of(Riot::Message) asserts(:to_s).equals(%q[should have "hope"]) end context "receiving #expected_message" do setup { topic.expected_message("hope") } asserts_topic.kind_of(Riot::Message) asserts(:to_s).equals(%q[expected "hope"]) end end # An AssertionMacro instance context "AssertionMacro#fail" do setup do macro = Riot::AssertionMacro.new macro.line = 5 macro.file = "foo" macro.fail("") end asserts_topic.includes(5) asserts_topic.includes("foo") end # AssertionMacro#failriot-0.12.7/test/core/runnable/assertion_test.rb0000644000004100000410000000405412261222026021714 0ustar www-datawww-datarequire 'teststrap' context "An assertion" do context "that is passing" do setup { Riot::Assertion.new("foo") { true } } asserts("to_s") { topic.to_s == "foo" } asserts(":pass is returned when evaluated") do topic.run(Riot::Situation.new) == [:pass, ""] end end # that is passing context "that is failing" do setup { Riot::Assertion.new("foo") { nil } } asserts("to_s") { topic.to_s == "foo" } asserts(":fail and message are evaluated") do topic.run(Riot::Situation.new)[0..1] end.equals([:fail, "Expected non-false but got nil instead"]) end # that is failing context "that is erroring" do setup do @exception = exception = Exception.new("blah") Riot::Assertion.new("baz") { raise exception } end asserts("to_s") { topic.to_s == "baz" } asserts(":error and exception are evaluated") do topic.run(Riot::Situation.new) == [:error, @exception] end end # that is erroring context "with no block to provide the actual value" do setup do @situation = Riot::Situation.new @situation.instance_variable_set(:@_topic, "hello") Riot::Assertion.new("test") end should("return a block that returns false") do topic.run(@situation) end.equals([:fail, "Expected non-false but got false instead", nil, nil]) end # with no block to provide the actual value context "with block expectation" do setup do @situation = Riot::Situation.new @situation.instance_variable_set(:@_topic, "hello") Riot::Assertion.new("test") { topic } end should("use block returning topic as default") do topic.equals { "hello" } topic.run(@situation) end.equals([:pass, %Q{is equal to "hello"}]) asserts("block expectation has access to the situation items") do topic.equals { @_topic } topic.run(@situation) end.equals([:pass, %Q{is equal to "hello"}]) end # with block expectation context "with symbolic description" do setup { "foo" } asserts(:upcase).equals("FOO") end end # An assertion block riot-0.12.7/test/core/runnable/teardown_test.rb0000644000004100000410000000266112261222026021532 0ustar www-datawww-datarequire 'teststrap' global_thang = Struct.new(:count).new(0) context "A context with a teardown" do setup do @a_context = Riot::Context.new("me") do setup { global_thang.count += 1 } asserts("teardown run") { global_thang.count }.equals(1) teardown { global_thang.count += 1 } end @a_context.run(MockReporter.new) end asserts("test passed") { topic.passes }.equals(1) asserts("teardown run") { global_thang.count }.equals(2) context "that has a nested context with teardowns" do setup do @a_context.context "nested" do setup { global_thang.count = 0 } asserts("no teardowns run") { global_thang.count }.equals(0) teardown { global_thang.count += 2 } end @a_context.run(MockReporter.new) end asserts("tests passed") { topic.passes }.equals(1) asserts("teardowns ran in local and parent context") { global_thang.count }.equals(3) end # that has a nested context with teardowns context "that has multiple teardowns in nested context" do setup do @a_context.context "nested" do setup { global_thang.count = 0 } teardown { global_thang.count += 2 } teardown { global_thang.count += 2 } end @a_context.run(MockReporter.new) end asserts("teardowns ran in local and parent context") { global_thang.count }.equals(5) end # that has multiple teardowns in nested context end # A context with a teardown riot-0.12.7/test/core/runnable/situation_test.rb0000644000004100000410000000051012261222026021715 0ustar www-datawww-datarequire 'teststrap' context "A situation" do setup do Riot::Situation.new end asserts("the topic is result of calling setup") do topic.setup { "foo" } topic.topic == "foo" end asserts("evaluate will return result of evaluation") do topic.evaluate { "foo" == "bar" } == false end end # A situation riot-0.12.7/test/core/reports/0000755000004100000410000000000012261222026016206 5ustar www-datawww-datariot-0.12.7/test/core/reports/story_reporter_test.rb0000644000004100000410000000273612261222026022704 0ustar www-datawww-datarequire 'teststrap' require 'stringio' context "StoryReporter" do setup do @out = StringIO.new Riot::StoryReporter.new(@out) end asserts("success message is stripped if nil") do topic.pass("foo", nil) @out.string end.matches(/\+ \e\[32mfoo\e\[0m\n/) asserts("failure message excludes line info if none provided") do @out.rewind topic.fail("foo", "bar", nil, nil) @out.string end.matches(/\- \e\[33mfoo: bar\e\[0m\n/) context 'reporting on an empty context' do setup do context = Riot::Context.new('empty context') { context("a nested empty context") {} }.run(topic) end should("not output context name") { @out.string }.empty end context "reporting on a non-empty context" do setup do Riot::Context.new('supercontext') { asserts("truth") { true } }.run(topic) end should('output context name') { @out.string }.matches(/supercontext/) should('output name of passed assertion') { @out.string }.matches(/truth/) end end # StoryReporter context "Plain StoryReporter" do setup do @out = StringIO.new Riot::StoryReporter.new(@out, {"plain" => true}) end asserts("success message is stripped if nil") do topic.pass("foo", nil) @out.string end.matches(/\+ foo\n/) asserts("failure message excludes line info if none provided") do @out.rewind topic.fail("foo", "bar", nil, nil) @out.string end.matches(/\- foo: bar\n/) end # Plain StoryReporter riot-0.12.7/test/core/reports/basic_reporter_test.rb0000644000004100000410000000375612261222026022610 0ustar www-datawww-datarequire 'teststrap' context "A reporter" do setup do Class.new(Riot::Reporter) do def pass(d, message) "passed(#{d}, #{message.inspect})"; end def fail(d, message, line, file) "failed(#{d}, #{message} on line #{line} in file #{file})"; end def error(d, e) "errored(#{d}, #{e})"; end def results(time); end end.new end # pass asserts("pass count increase when :pass sent to #report") do topic.report("", [:pass]) topic.passes end.equals(1) asserts("description sent to #pass") do topic.report("hi mom", [:pass]) end.equals("passed(hi mom, nil)") # fail asserts("fail count increase when :fail sent to #report") do topic.report("", [:fail, ""]) topic.failures end.equals(1) asserts("description, message, line and file sent to #fail") do topic.report("hi mom", [:fail, "how are you", 4, "foo"]) end.equals("failed(hi mom, how are you on line 4 in file foo)") # error asserts("error count increase when :error sent to #report") do topic.report("", [:error, ""]) topic.errors end.equals(1) asserts("error count increase when :setup_error sent to #report") do topic.report("", [:setup_error, ""]) topic.errors end.equals(2) asserts("description sent to #error") do topic.report("break it down", [:error, "error time"]) end.equals("errored(break it down, error time)") context "instance" do setup { Riot::Reporter.new } should("return self invoking new") { topic.new }.equals { topic } should("accept an options hash") { topic.new({}) }.equals { topic } end context "with no errors or failures" do hookup { topic.report("foo", [:pass, nil]) } asserts(:success?) end context "with failures and no errors" do hookup { topic.report("foo", [:fail, "blah"]) } asserts(:success?).equals(false) end context "with errors and no failures" do hookup { topic.report("foo", [:error, Exception.new("boogers")]) } asserts(:success?).equals(false) end end # A reporter riot-0.12.7/test/core/reports/dot_matrix_reporter_test.rb0000644000004100000410000000302712261222026023670 0ustar www-datawww-datarequire 'teststrap' context "DotMatrixReporter" do setup do @out = StringIO.new Riot::DotMatrixReporter.new(@out) end context "with a passing test" do setup do context = Riot::Context.new('whatever') do asserts('true') { true } end context.run(topic) @out.string end asserts_topic('puts a dot').matches('.') end context 'with a failing test' do setup do Riot::Context.new('whatever') do asserts('nope!') { false } end.run(topic) topic.results(100) @out.string end asserts_topic('puts an F').matches('F') asserts_topic("puts the full context + assertion name").matches('whatever asserts nope!') asserts_topic("puts the failure reason").matches(/Expected .* but got false instead/) end context 'with an error test' do setup do Riot::Context.new('whatever') do asserts('bang') { raise "BOOM" } end.run(topic) topic.results(100) @out.string end asserts_topic('puts an E').matches('E') asserts_topic('puts the full context + assertion name').matches('whatever asserts bang') asserts_topic('puts the exception message').matches('BOOM') # : is the last thing in the stack trace asserts_topic('puts the filtered exception backtrace').matches do if RUBY_VERSION =~ /^1.8.\d+/ /#{__FILE__}:\d+\n\n.*$\n\z/ else /#{__FILE__}:\d+:[^\n]*\n\n.*$\n\z/ end end end end riot-0.12.7/test/core/assertion_macros/0000755000004100000410000000000012261222026020063 5ustar www-datawww-datariot-0.12.7/test/core/assertion_macros/equals_test.rb0000644000004100000410000000472212261222026022746 0ustar www-datawww-datarequire 'teststrap' # Using == to verify the test because this is the test for :equals itself. Look at assertion_test_passes # and assertion_test_fails for testing other macros. context "An equals assertion macro" do setup do Riot::Assertion.new("blue") { "foo" } end asserts(":pass when expectation met") do topic.equals("foo").run(Riot::Situation.new) == [:pass, %Q{is equal to "foo"}] end context "that is failing" do setup { topic.equals("bar").run(Riot::Situation.new) } asserts(":fail") { topic.first == :fail } asserts("message") { topic[1] == %Q{expected "bar", not "foo"} } end # that is failing context "with numeric topic" do setup do Riot::Assertion.new("blue") { 31415 } end asserts("failure") do topic.equals(30000..32000).run(Riot::Situation.new)[0..1] == [:fail, "expected 30000..32000, not 31415"] end end # with numeric topic context "with block as the expectation" do asserts(":pass when block expectation met") do topic.equals { "foo" }.run(Riot::Situation.new) end.equals([:pass, %Q{is equal to "foo"}]) asserts(":fail with message when block expectation not met") do topic.equals { "bar" }.run(Riot::Situation.new)[0..1] end.equals([:fail, %Q{expected "bar", not "foo"}]) end # with block as the expectation end # An equals assertion macro context "A negative equals assertion macro" do setup do Riot::Assertion.new("that flirgy", true) { "foo" } end asserts(":pass when values do not match") do topic.equals("bar").run(Riot::Situation.new) == [:pass, %Q{is equal to "bar" when it is "foo"}] end asserts(":fail when values do match") do topic.equals("foo").run(Riot::Situation.new)[0..1] == [:fail, %Q{did not expect "foo"}] end asserts("result of evaluating when number outside of range") do Riot::Assertion.new("blue", true) { 31415 }.equals(30000..32000).run(Riot::Situation.new) end.equals([:pass, "is equal to 30000..32000 when it is 31415"]) context "with block as the expectation" do asserts(":pass when block expectation values do not equal") do topic.equals { "bazzle" }.run(Riot::Situation.new) end.equals([:pass, %Q{is equal to "bazzle" when it is "foo"}]) asserts(":fail with message when block expectation values do equal") do topic.equals { "foo" }.run(Riot::Situation.new)[0..1] end.equals([:fail, %Q{did not expect "foo"}]) end # with block as the expectation end # A negative assertion macro riot-0.12.7/test/core/assertion_macros/includes_test.rb0000644000004100000410000000135412261222026023260 0ustar www-datawww-datarequire 'teststrap' context "An includes assertion macro" do setup do Riot::Assertion.new("an array") { [1, 6, 42, 7] } end assertion_test_passes("when array includes 42", "includes 42") { topic.includes(42) } assertion_test_fails("when 99 not included in array", "expected [1, 6, 42, 7] to include 99") do topic.includes(99) end end # An includes assertion macro context "A negative includes assertion macro" do setup do Riot::Assertion.new("an array", true) { [1, 6, 42, 7] } end assertion_test_passes("when array doesn't include 69", "includes 69") { topic.includes(69) } assertion_test_fails("when 42 is included in array", "expected [1, 6, 42, 7] to not include 42") do topic.includes(42) end end riot-0.12.7/test/core/assertion_macros/assigns_test.rb0000644000004100000410000000344112261222026023120 0ustar www-datawww-datarequire 'teststrap' context "An assigns assertion macro" do setup do item = Object.new item.instance_eval { @foo = 1; @nil_val = nil } Riot::Assertion.new("test") { item } end assertion_test_passes("when foo is defined","assigns :foo") { topic.assigns(:foo) } assertion_test_passes("when foo is defined with expected value","assigns :foo with 1") { topic.assigns(:foo, 1) } assertion_test_fails("when foo does not match expectation", "expected :foo to be assigned with 2, not 1") do topic.assigns(:foo, 2) end assertion_test_fails("when bar is not define", "expected :bar to be assigned a value") do topic.assigns(:bar) end assertion_test_fails("when var assigned nil value", "expected :nil_val to be assigned a value") do topic.assigns(:nil_val) end end # An assigns assertion macro context "A negative assigns assertion macro" do setup do item = Object.new item.instance_eval { @foo = 1; @nil_val = nil } Riot::Assertion.new("test", true) { item } end asserts(":pass when @bar is not defined") do topic.assigns(:bar).run(Riot::Situation.new) end.equals([:pass, "assigns :bar"]) asserts(":pass when @nil_val is actually nil") do topic.assigns(:nil_val).run(Riot::Situation.new) end.equals([:pass, "assigns :nil_val"]) asserts(":pass when @foo does not equal 2") do topic.assigns(:foo, 2).run(Riot::Situation.new) end.equals([:pass, "assigns :foo with 2"]) asserts(":fail when @foo is defined") do topic.assigns(:foo).run(Riot::Situation.new)[0..1] end.equals([:fail, "expected :foo to not be assigned a value"]) asserts(":fail when @foo does equal 1") do topic.assigns(:foo, 1).run(Riot::Situation.new)[0..1] end.equals([:fail, "expected :foo to not be assigned with 1"]) end # A negative assigns assertion macro riot-0.12.7/test/core/assertion_macros/respond_to_test.rb0000644000004100000410000000176212261222026023631 0ustar www-datawww-datarequire 'teststrap' context "A respond_to assertion macro" do setup { Riot::Assertion.new("foo") { "bar" } } assertion_test_passes("when method is defined", "responds to :each_byte") { topic.respond_to(:each_byte) } assertion_test_passes("using responds_to alias", "responds to :length") { topic.responds_to(:length) } assertion_test_fails("when method not defined", "expected method :goofballs is not defined") do topic.respond_to(:goofballs) end end # A respond_to assertion macro context "A negative respond_to assertion macro" do setup { Riot::Assertion.new("foo", true) { "bar" } } assertion_test_fails("when method is defined", "expected method :each_byte is defined") do topic.respond_to(:each_byte) end assertion_test_fails("using responds_to alias", "expected method :length is defined") do topic.responds_to(:length) end assertion_test_passes("when method is not defined", "responds to :goofballs") do topic.respond_to(:goofballs) end end riot-0.12.7/test/core/assertion_macros/exists_test.rb0000644000004100000410000000210312261222026022762 0ustar www-datawww-datarequire 'teststrap' context "An exists assertion macro" do helper(:assert_exists) do |o| Riot::Assertion.new("test") { o }.exists.run(Riot::Situation.new) end asserts(":pass when result has a value") do assert_exists("foo") end.equals([:pass, "does exist"]) asserts(":pass because empty string is considered a value") do assert_exists("") end.equals([:pass, "does exist"]) asserts(":fail with message when value is nil") do assert_exists(nil)[0..1] end.equals([:fail, "expected a non-nil value"]) end # An exists assertion macro context "A negative exists assertion macro" do helper(:assert_exists) do |o| Riot::Assertion.new("test", true) { o }.exists.run(Riot::Situation.new) end asserts(":fail when string") do assert_exists("foo")[0..1] end.equals([:fail, "expected a nil value"]) asserts ":fail when string empty" do assert_exists("")[0..1] end.equals([:fail, "expected a nil value"]) asserts(":pass when nil") do assert_exists(nil) end.equals([:pass, "does exist"]) end # A negative exists assertion macro riot-0.12.7/test/core/assertion_macros/size_test.rb0000644000004100000410000000703212261222026022423 0ustar www-datawww-datarequire 'teststrap' context "A size assertion macro" do helper(:assert_size) { |sizable, expected_size| Riot::Assertion.new("test") { sizable }.size(expected_size) } assertion_test_passes("when string's size is as expected", "is of size 10") do assert_size("washington", 10) end assertion_test_passes("when string's size is in given range", "is of size 9..12") do assert_size("washington", 9..12) end assertion_test_fails("when string's size is not as expected", "expected size of \"washington\" to be 11, not 10") do assert_size("washington", 11) end assertion_test_fails("when string's size is out of range", "expected size of \"washington\" to be 11..13, not 10") do assert_size("washington", 11..13) end assertion_test_passes("when an array's size is as expected", "is of size 3") { assert_size([1, 2, 3], 3) } assertion_test_passes("when an array's size is in given range", "is of size 3..4") do assert_size([1, 2, 3], 3..4) end assertion_test_fails("when an array's size is not as expected", "expected size of [1, 2, 3] to be 2, not 3") do assert_size([1, 2, 3], 2) end assertion_test_fails("when an array's size is out of range", "expected size of [1, 2, 3] to be 4..6, not 3") do assert_size([1, 2, 3], 4..6) end assertion_test_passes("when a hash size is as expected", "is of size 1") do assert_size({:name => 'washington'}, 1) end assertion_test_passes("when a hash size is in range", "is of size 1...3") do assert_size({:name => 'washington'}, 1...3) end assertion_test_fails("when a hash size is not as expected", "expected size of {} to be 2, not 0") do assert_size({}, 2) end assertion_test_fails("when a hash size is out of range", "expected size of {} to be 2...4, not 0") do assert_size({}, 2...4) end end context "A negative size assertion macro" do helper(:deny_size) { |sizable, expected_size| Riot::Assertion.new("test", true) { sizable }.size(expected_size) } assertion_test_fails("when string's size is as expected", 'expected size of "washington" to not be 10, not 10') do deny_size("washington", 10) end assertion_test_fails("when string's size is in given range", 'expected size of "washington" to not be 9..12, not 10') do deny_size("washington", 9..12) end assertion_test_passes("when string's size is not as expected", 'is size 11') do deny_size("washington", 11) end assertion_test_passes("when string's size is out of range", 'is size 11..13') do deny_size("washington", 11..13) end assertion_test_fails("when an array's size is as expected", 'expected size of [1, 2, 3] to not be 3, not 3') do deny_size([1, 2, 3], 3) end assertion_test_fails("when an array's size is in given range", 'expected size of [1, 2, 3] to not be 3..4, not 3') do deny_size([1, 2, 3], 3..4) end assertion_test_passes("when an array's size is not as expected", "is size 2") do deny_size([1, 2, 3], 2) end assertion_test_passes("when an array's size is out of range", "is size 4..6") do deny_size([1, 2, 3], 4..6) end assertion_test_fails("when a hash size is as expected", 'expected size of {:a=>"b"} to not be 1, not 1') do deny_size({:a => 'b'}, 1) end assertion_test_fails("when a hash size is in range", 'expected size of {:a=>"b"} to not be 1...3, not 1') do deny_size({:a => 'b'}, 1...3) end assertion_test_passes("when a hash size is not as expected", "is size 2") do deny_size({}, 2) end assertion_test_passes("when a hash size is out of range", "is size 2...4") do deny_size({}, 2...4) end end riot-0.12.7/test/core/assertion_macros/nil_test.rb0000644000004100000410000000141712261222026022234 0ustar www-datawww-datarequire 'teststrap' context "A nil assertion macro" do helper(:assert_nil) { |o| Riot::Assertion.new("foo") { o }.nil.run(Riot::Situation.new) } asserts(":pass when result is nil") { assert_nil(nil) }.equals([:pass, "is nil"]) asserts(":fail with message") { assert_nil("a")[0..1] }.equals([:fail, %Q{expected nil, not "a"}]) end # A nil assertion macro context "A negative nil assertion macro" do helper(:assert_not_nil) { |o| Riot::Assertion.new("foo", true) { o }.nil.run(Riot::Situation.new) } asserts(":pass when result is not nil") { assert_not_nil(1) }.equals([:pass, "is nil"]) asserts(":fail with message") { assert_not_nil(nil)[0..1] }.equals([:fail, %Q{expected is nil, not "non-nil"}]) end # A negative nil assertion macro riot-0.12.7/test/core/assertion_macros/same_elements_test.rb0000644000004100000410000000251212261222026024270 0ustar www-datawww-datarequire 'teststrap' context "A same_elements assertion macro" do setup { Riot::Assertion.new("test") { ["foo", "bar", 69] } } assertion_test_passes(%Q{when [69, "foo", "bar"] are returned},%Q{has same elements as [69, "foo", "bar"]}) do topic.same_elements([69, "foo", "bar"]) end assertion_test_passes(%Q{when [69, "foo", "bar"] are returned in any order},%Q{has same elements as ["foo", "bar", 69]}) do topic.same_elements(["foo", "bar", 69]) end assertion_test_fails("when elements do not match", %Q{expected elements ["foo", "bar", 96] to match ["foo", "bar", 69]}) do topic.same_elements(["foo", "bar", 96]) end end # A same_elements assertion macro context "A negative same_elements assertion macro" do setup { Riot::Assertion.new("test", true) { ["foo","bar", 69] } } assertion_test_fails("when elements match", %Q{expected elements [69, "foo", "bar"] not to match ["foo", "bar", 69]}) do topic.same_elements([69, "foo", "bar"]) end assertion_test_fails("when any elements match", %Q{expected elements ["foo", "bar", 69] not to match ["foo", "bar", 69]}) do topic.same_elements(["foo", "bar", 69]) end assertion_test_passes("when elements do not match",%Q{has same elements as ["foo", "bar", 96]}) do topic.same_elements(["foo", "bar", 96]) end end # A negative same_elements macro riot-0.12.7/test/core/assertion_macros/any_test.rb0000644000004100000410000000310512261222026022235 0ustar www-datawww-datarequire 'teststrap' context "An any assertion macro" do helper(:assert_any) do |o| Riot::Assertion.new("test") { o }.any end assertion_test_passes("when an array has items", "has items") { assert_any([1]) } assertion_test_fails("when an array is empty", "expected [] to have items") do assert_any([]) end assertion_test_passes("when a hash has items", "has items") { assert_any({:name => 'washington'}) } assertion_test_fails("when a hash is empty", "expected {} to have items") do assert_any({}) end end context "A negative, any assertion macro" do helper(:any) do |o| Riot::Assertion.new("test", true) { o }.any end asserts(":error when value is nil") do any(nil).run(Riot::Situation.new)[0] # No method any? on nil end.equals(:error) asserts(":pass when string is empty") do any("").run(Riot::Situation.new) end.equals([:pass, "has items"]) asserts(":pass when array is empty") do any([]).run(Riot::Situation.new) end.equals([:pass, "has items"]) asserts(":pass when hash is empty") do any({}).run(Riot::Situation.new) end.equals([:pass, "has items"]) asserts(":fail when string is empty") do any("foo").run(Riot::Situation.new)[0..1] end.equals([:fail, %Q{expected "foo" not to have items}]) asserts(":fail when array has items") do any([1,2]).run(Riot::Situation.new)[0..1] end.equals([:fail, %Q{expected [1, 2] not to have items}]) asserts(":fail when hash has items") do any({"bar" => "baz"}).run(Riot::Situation.new)[0..1] end.equals([:fail, %Q{expected {"bar"=>"baz"} not to have items}]) end riot-0.12.7/test/core/assertion_macros/matches_test.rb0000644000004100000410000000270112261222026023073 0ustar www-datawww-datarequire 'teststrap' context "A matching assertion macro" do setup { Riot::Assertion.new("foo") { "abc" } } assertion_test_passes("when expression matches actual", %Q{matches /abc/}) { topic.matches(/abc/) } assertion_test_fails("when expression fails to match", "expected /abcd/ to match \"abc\"") do topic.matches(/abcd/) end context "with integer based topic" do setup { Riot::Assertion.new("foo") { 42 } } assertion_test_passes("actual value converted to string", %Q{matches /^42$/}) do topic.matches(/^42$/) end assertion_test_fails("actual value converted to string", %Q{expected /^52$/ to match 42}) do topic.matches(/^52$/) end end end # A matching assertion macro context "A negative matching assertion macro" do setup { Riot::Assertion.new("foo", true) { "abc" } } assertion_test_fails("when expression matches actual", 'expected /abc/ not to match "abc"') do topic.matches(/abc/) end assertion_test_passes("when expression does not match", 'matches /abcd/') do topic.matches(/abcd/) end context "with integer based topic" do setup { Riot::Assertion.new("foo", true) { 42 } } assertion_test_fails("actual value converted to string", 'expected /^42$/ not to match 42') do topic.matches(/^42$/) end assertion_test_passes("actual value converted to string", 'matches /^52$/') do topic.matches(/^52$/) end end end # A negative matching assertion macro riot-0.12.7/test/core/assertion_macros/empty_test.rb0000644000004100000410000000312012261222026022601 0ustar www-datawww-datarequire 'teststrap' context "An empty assertion macro" do helper(:assert_empty) do |o| Riot::Assertion.new("test") { o }.empty end assertion_test_passes("when string is empty", "is empty") { assert_empty("") } assertion_test_fails("when string has content", "expected \" \" to be empty") do assert_empty(" ") end assertion_test_passes("when an array is empty", "is empty") { assert_empty([]) } assertion_test_fails("when an array has items", "expected [1] to be empty") do assert_empty([1]) end assertion_test_passes("when a hash is empty", "is empty") { assert_empty({}) } assertion_test_fails("when a hash has items", "expected {:name=>\"washington\"} to be empty") do assert_empty({:name => 'washington'}) end end context "A negative empty assertion macro" do helper(:assert_empty) do |o| Riot::Assertion.new("test", true) { o }.empty.run(Riot::Situation.new) end asserts("when string is not empty") do assert_empty("foo") end.equals([:pass, "is empty"]) asserts("when string is empty") do assert_empty("")[0..1] end.equals([:fail, "expected \"\" to not be empty"]) asserts("when array is not empty") do assert_empty([1]) end.equals([:pass, "is empty"]) asserts("when array is empty") do assert_empty([])[0..1] end.equals([:fail, "expected [] to not be empty"]) asserts("when hash is not empty") do assert_empty({:boo => "blux"}) end.equals([:pass, "is empty"]) asserts("when hash is empty") do assert_empty({})[0..1] end.equals([:fail, "expected {} to not be empty"]) end # A negative empty assertion macro riot-0.12.7/test/core/assertion_macros/equivalent_to_test.rb0000644000004100000410000000411612261222026024330 0ustar www-datawww-datarequire 'teststrap' # Using == to verify the test because this is the test for :equals itself. Look at assertion_test_passes # and assertion_test_fails for testing other macros. context "An equivalent_to assertion macro" do setup { Riot::Assertion.new("red") { "what" } } asserts("String is equivalent to 'what'") do topic.equivalent_to(String).run(Riot::Situation.new) end.equals([:pass, "is equivalent to String"]) asserts("an array is not equivalent to 'what'") do topic.equivalent_to([]).run(Riot::Situation.new)[0..1] end.equals([:fail, 'expected "what" to be equivalent to []']) context "with numeric topic" do setup { Riot::Assertion.new("blue") { 31413 } } asserts(":pass when in expected range") do topic.equivalent_to(30000..32000).run(Riot::Situation.new) end.equals([:pass, "is equivalent to 30000..32000"]) asserts ":fail when not in expected range" do topic.equivalent_to(32000..33000).run(Riot::Situation.new)[0..1] end.equals([:fail, 'expected 31413 to be equivalent to 32000..33000']) end # with numeric topic end # An equivalent_to assertion macro context "A negative equivalent_to assertion macro" do setup { Riot::Assertion.new("red", true) { "what" } } asserts("String is not equivalent to 'what'") do topic.equivalent_to(String).run(Riot::Situation.new)[0..1] end.equals([:fail, 'expected "what" not to be equivalent to String']) asserts("an array is not equivalent to 'what'") do topic.equivalent_to([]).run(Riot::Situation.new) end.equals([:pass, "is equivalent to []"]) context "with numeric topic" do setup { Riot::Assertion.new("blue", true) { 31413 } } asserts(":fail when not in expected range") do topic.equivalent_to(30000..32000).run(Riot::Situation.new)[0..1] end.equals([:fail, "expected 31413 not to be equivalent to 30000..32000"]) asserts ":pass when in expected range" do topic.equivalent_to(32000..33000).run(Riot::Situation.new) end.equals([:pass, "is equivalent to 32000..33000"]) end # with numeric topic end # A negative equivalent_to assertion macro riot-0.12.7/test/core/assertion_macros/kind_of_test.rb0000644000004100000410000000213512261222026023061 0ustar www-datawww-datarequire 'teststrap' context "A kind_of assertion macro" do assertion_test_passes(":pass when specific result is a kind of String", "is a kind of String") do Riot::Assertion.new("foo") { "a" }.kind_of(String) end assertion_test_fails(":fail when not a kind of String", "expected kind of String, not Fixnum") do Riot::Assertion.new("foo") { 0 }.kind_of(String) end assertion_test_fails(":fail when nil", "expected kind of String, not NilClass") do Riot::Assertion.new("foo") { }.kind_of(String) end end # A kind_of assertion macro context "A negative kind_of assertion macro" do assertion_test_passes(":pass when specific result is not a kind of String", "is a kind of String") do Riot::Assertion.new("foo", true) { 1 }.kind_of(String) end assertion_test_fails(":fail when a kind of String", "expected not kind of String, not String") do Riot::Assertion.new("foo", true) { "a" }.kind_of(String) end assertion_test_passes(":pass when nil", "is a kind of String") do Riot::Assertion.new("foo", true) { }.kind_of(String) end end # A negative kind_of assert macro riot-0.12.7/test/core/assertion_macros/raises_test.rb0000644000004100000410000000515512261222026022743 0ustar www-datawww-datarequire 'teststrap' class Whoops < Exception; end context "A raises assertion macro" do helper(:asserts_raises) { |o| Riot::Assertion.new("foo") { raise Whoops, o } } assertion_test_passes("when expected exception is raised", "raises Whoops") do asserts_raises(nil).raises(Whoops) end assertion_test_fails("when unexpected exception is raised", "expected to raise Exception, not Whoops") do asserts_raises(nil).raises(Exception) end assertion_test_fails("when nothing was raised", "expected to raise Whoops, but raised nothing") do Riot::Assertion.new("foo") { "barf" }.raises(Whoops) end assertion_test_passes("when provided message equals expected message", %Q{raises Whoops with message "Mom"}) do asserts_raises('Mom').raises(Whoops, 'Mom') end assertion_test_fails("when messages aren't equal", %Q{expected "Mom" for message, not "Dad"}) do asserts_raises('Dad').raises(Whoops, 'Mom') end assertion_test_passes("when provided message matches expected message", %Q{raises Whoops with message /Mom/}) do asserts_raises('Mom').raises(Whoops, /Mom/) end assertion_test_fails("when messages don't match", %Q{expected /Mom/ for message, not "Dad"}) do asserts_raises('Dad').raises(Whoops, /Mom/) end end # A raises assertion macro context "A negative raises assertion macro" do helper(:deny_raises) { |o| Riot::Assertion.new("foo", true) { raise Whoops, o } } assertion_test_fails("when expected exception is raised", "expected to not raise Whoops") do deny_raises(nil).raises(Whoops) end assertion_test_passes("when unexpected exception is raised", "raises Exception") do deny_raises(nil).raises(Exception) end assertion_test_passes("when nothing was raised", "raises Whoops") do Riot::Assertion.new("foo", true) { "barf" }.raises(Whoops) end assertion_test_fails("when provided message equals expected message", 'expected to not raise Whoops with message "Mom", but raised Whoops with message "Mom"') do deny_raises('Mom').raises(Whoops, 'Mom') end assertion_test_passes("when messages and exception aren't equal", 'raises Exception with message "Dad"') do deny_raises('Mom').raises(Exception, 'Dad') end assertion_test_fails("when provided message matches expected message", 'expected to not raise Whoops with message /Mom/, but raised Whoops with message "Mom"') do deny_raises('Mom').raises(Whoops, /Mom/) end assertion_test_fails("when messages don't match", "expected to not raise Whoops with message /Mom/, but raised Whoops with message \"Dad\"") do deny_raises('Dad').raises(Whoops,/Mom/) end end # A raises assertion macro riot-0.12.7/test/core/assertion_macros/raises_kind_of_test.rb0000644000004100000410000000707312261222026024435 0ustar www-datawww-datarequire 'teststrap' class Whoops < Exception; end class SubWhoops < Whoops; end context "A raises_kind_of assertion macro" do helper(:asserts_raises) { |o| Riot::Assertion.new("foo") { raise Whoops, o } } assertion_test_passes("when expected exception is raised", "raises kind of Whoops") do asserts_raises(nil).raises_kind_of(Whoops) end assertion_test_fails("when a superclass of the expected exception is raised", "expected to raise kind of SubWhoops, not Whoops") do asserts_raises(nil).raises_kind_of(SubWhoops) end assertion_test_passes("when a subclass of the expected exception is raised", "raises kind of Exception") do asserts_raises(nil).raises_kind_of(Exception) end assertion_test_fails("when nothing was raised", "expected to raise kind of Whoops, but raised nothing") do Riot::Assertion.new("foo") { "barf" }.raises_kind_of(Whoops) end assertion_test_passes("when provided message equals expected message", %Q{raises kind of Whoops with message "Mom"}) do asserts_raises('Mom').raises_kind_of(Whoops, 'Mom') end assertion_test_fails("when messages aren't equal", %Q{expected "Mom" for message, not "Dad"}) do asserts_raises('Dad').raises_kind_of(Whoops, 'Mom') end assertion_test_passes("when provided message matches expected message", %Q{raises kind of Whoops with message /Mom/}) do asserts_raises('Mom').raises_kind_of(Whoops, /Mom/) end assertion_test_fails("when messages don't match", %Q{expected /Mom/ for message, not "Dad"}) do asserts_raises('Dad').raises_kind_of(Whoops, /Mom/) end end # A raises_kind_of assertion macro context "A negative raises_kind_of assertion macro" do helper(:deny_raises) { |o| Riot::Assertion.new("foo", true) { raise Whoops, o } } assertion_test_fails("when expected exception is raised", "expected to not raise kind of Whoops") do deny_raises(nil).raises_kind_of(Whoops) end assertion_test_fails("when a subclass of the expected exception is raised", "expected to not raise kind of Whoops") do Riot::Assertion.new("foo", true) { raise SubWhoops }.raises_kind_of(Whoops) end assertion_test_passes("when unexpected exception is raised", "raises kind of SubWhoops") do deny_raises(nil).raises_kind_of(SubWhoops) end assertion_test_passes("when nothing was raised", "raises kind of Whoops") do Riot::Assertion.new("foo", true) { "barf" }.raises_kind_of(Whoops) end assertion_test_fails("when provided message equals expected message", 'expected to not raise kind of Whoops with message "Mom", but raised Whoops with message "Mom"') do deny_raises('Mom').raises_kind_of(Whoops, 'Mom') end assertion_test_passes("when messages and exception aren't equal", 'raises kind of ArgumentError with message "Dad"') do deny_raises('Mom').raises_kind_of(ArgumentError, 'Dad') end assertion_test_fails("when provided message matches expected message", 'expected to not raise kind of Whoops with message /Mom/, but raised Whoops with message "Mom"') do deny_raises('Mom').raises_kind_of(Whoops, /Mom/) end assertion_test_fails("when messages don't match", "expected to not raise kind of Whoops with message /Mom/, but raised Whoops with message \"Dad\"") do deny_raises('Dad').raises_kind_of(Whoops, /Mom/) end end # A raises_kind_of assertion macro riot-0.12.7/test/benchmark/0000755000004100000410000000000012261222026015512 5ustar www-datawww-datariot-0.12.7/test/benchmark/message_concatenation.rb0000644000004100000410000000417312261222026022375 0ustar www-datawww-datarequire 'benchmark' class BlankSlate instance_methods.each { |meth| undef_method(meth) unless meth.to_s =~ /^(__|object_id)/ } end class NormalMessage < BlankSlate def initialize(*phrases) @message = ""; _phrase(*phrases) end def to_s; @message; end def method_missing(meth, *phrases, &blk) push(meth.to_s.gsub('_', ' ')); _phrase(*phrases); end def comma(str, *phrases) raise Exception, "Whoops - comma"; end def but(*phrases); comma("but", *phrases); end def not(*phrases); comma("not", *phrases); end def push(str) raise Exception, "Whoops - push"; end private def _concat(str) (@message << str).strip!; self; end def _phrase(*phrases) phrases.each { |phrase| push(phrase.inspect) }; self; end end # Message # + class PlusMessage < NormalMessage def comma(str, *phrases) _concat(", " + str); _phrase(*phrases); end def push(str) _concat(" " + str); end end # Message # << class AppendMessage < NormalMessage def comma(str, *phrases) _concat(", " << str); _phrase(*phrases); end def push(str) _concat(" " << str); end end # Message # Experimental class ExperimentalMessage < BlankSlate def initialize(*phrases) @chunks = []; _inspect(phrases) end def to_s; @chunks.join; end def method_missing(meth, *phrases, &blk) push(meth.to_s.gsub('_', ' ')); _inspect(phrases); end def comma(str, *phrases) _concat([", ", str]); _inspect(phrases); end def but(*phrases); comma("but", *phrases); end def not(*phrases); comma("not", *phrases); end def push(str) _concat([" ", str]); end private def _concat(chunks) @chunks.concat(chunks); self; end def _inspect(phrases) phrases.each { |phrase| push(phrase.inspect) }; self; end end # Message # # Benchmarking Benchmark.bmbm do |x| def message_test(klass) STDOUT.puts(klass.new.comma("yes").push("no").foo.bar("baz").to_s) 10_000.times do klass.new.comma("yes").push("no").foo.bar("baz").to_s end end x.report("+ based message") do message_test(PlusMessage) end x.report("<< based message") do message_test(AppendMessage) end x.report("experimental message") do message_test(ExperimentalMessage) end end riot-0.12.7/test/benchmark/riot_vs_minitest.rb0000644000004100000410000000141112261222026021435 0ustar www-datawww-data$:.unshift(File.dirname(__FILE__) + "/../../lib") require 'benchmark' # # Model class Room attr_reader :name def initialize(name) @name = name end end # # Riot require 'riot' context "a room" do setup { Room.new("bed") } asserts("name") { topic.name }.equals("bed") end # a room # # MiniTest::Unit require 'rubygems' require 'minitest/unit' class RoomTest < MiniTest::Unit::TestCase def setup @room = Room.new("bed") end def test_room_should_be_named_bed assert_equal "bed", @room.name end end # # Benchmarking n = 100 * 100 Benchmark.bmbm do |x| x.report("Riot") do Riot.silently! Riot.alone! n.times { Riot.run } end x.report("MiniTest") do n.times { RoomTest.new("Blah").run(MiniTest::Unit.new) } end end riot-0.12.7/test/benchmark/same_elements_vs_set.rb0000644000004100000410000000147712261222026022254 0ustar www-datawww-datarequire 'benchmark' # # Benchmarking n = 100 * 100 Benchmark.bmbm do |x| x.report("Set theory") do require 'set' def set_theory(expected, actual) a = Set.new(expected) b = Set.new(actual) a == b end n.times do array = ["a", 1, {:foo => :bar}] set_theory(array, array.reverse) end end x.report("same_elements from shoulda (sorta)") do def same_elements(a1, a2) [:select, :inject, :size].each do |m| [a1, a2].each { |a| a.respond_to?(m) || return } end a1h = a1.inject({}) { |h,e| h[e] = a1.select { |i| i == e }.size; h } a2h = a2.inject({}) { |h,e| h[e] = a2.select { |i| i == e }.size; h } a1h == a2h end n.times do array = ["a", 1, {:foo => :bar}] same_elements(array, array.reverse) end end end riot-0.12.7/test/benchmark/simple_context_and_assertions.rb0000644000004100000410000000223612261222026024173 0ustar www-datawww-data$:.unshift(File.dirname(__FILE__) + "/../../lib/") require 'benchmark' # # Model class Room attr_reader :name def initialize(name) @name = name end end # # Test::Unit require 'test/unit' Test::Unit.run = true require 'test/unit/ui/console/testrunner' class RoomTest < Test::Unit::TestCase def setup @room = Room.new("bed") end def test_room_should_be_named_bed assert_equal "bed", @room.name end end # # Shoulda require 'rubygems' require 'shoulda' class ShouldaRoomTest < Test::Unit::TestCase def setup @room = Room.new("bed") end should("be named 'bed'") { assert_equal "bed", @room.name } end # # Riot require 'riot' context "a room" do setup { Room.new("bed") } asserts("name") { topic.name }.equals("bed") end # a room # # Benchmarking n = 100 * 100 Benchmark.bmbm do |x| x.report("Riot") do Riot.silently! Riot.alone! n.times { Riot.run } end x.report("Test::Unit") do n.times { Test::Unit::UI::Console::TestRunner.new(RoomTest, Test::Unit::UI::SILENT) } end x.report("Shoulda") do n.times { Test::Unit::UI::Console::TestRunner.new(ShouldaRoomTest, Test::Unit::UI::SILENT) } end end riot-0.12.7/test/teststrap.rb0000644000004100000410000000216712261222026016144 0ustar www-datawww-data$:.unshift(File.dirname(__FILE__) + "/../lib/") require 'rubygems' require 'bundler/setup' require 'riot' Riot.verbose Riot.pretty_dots if ENV["TM_MODE"] module Riot module AssertionTestContextMacros def assertion_test_passes(description, success_message="", &block) context(description) do setup(&block) setup { topic.run(Riot::Situation.new) } asserts("pass") { topic.first }.equals(:pass) asserts("success message") { topic.last }.equals(success_message) end end def assertion_test_fails(description, failure_message, &block) context(description) do setup(&block) asserts("failure") { topic.run(Riot::Situation.new).first }.equals(:fail) asserts("failure message") { topic.run(Riot::Situation.new)[1] }.equals(failure_message) end end end # AssertionTestContextMacros end # Riot Riot::Context.instance_eval { include Riot::AssertionTestContextMacros } class MockReporter < Riot::Reporter def pass(description, message); end def fail(description, message, line, file); end def error(description, e); end def results; end end riot-0.12.7/test/extensions/0000755000004100000410000000000012261222026015757 5ustar www-datawww-datariot-0.12.7/test/extensions/rrriot_test.rb0000644000004100000410000000543512261222026020673 0ustar www-datawww-datarequire 'teststrap' require 'riot/rr' context "Riot with RR support" do asserts("RR methods are available to an RR::Situation") do Riot::RR::Situation.ancestors end.includes(::RR::Adapters::RRMethods) asserts("assertion passes when RR is satisfied") do situation = Riot::RR::Situation.new Riot::RR::Assertion.new("Satisfied") { true }.run(situation) end.equals([:pass, ""]) asserts("assertion that would otherwise pass fails with RR message when RR is displeased") do situation = Riot::RR::Situation.new Riot::RR::Assertion.new("Displeased") { mock!.hello }.run(situation) end.equals([:fail, "hello() Called 0 times. Expected 1 times."]) fake_exception = RuntimeError.new("ooga booga") asserts("assertion that would otherwise fail or error does so intact even when RR is displeased") do situation = Riot::RR::Situation.new Riot::RR::Assertion.new("Displeased") do mock!.hello raise fake_exception end.run(situation) end.equals { [:error, fake_exception] } asserts("RR verification is reset between assertion runs") do situation = Riot::RR::Situation.new Riot::RR::Assertion.new("Displeased") { mock!.hello; mock!.what }.run(situation) Riot::RR::Assertion.new("Displeased differently") { mock!.goodbye }.run(situation) end.equals([:fail, "goodbye() Called 0 times. Expected 1 times."]) context "when using the RR context" do setup { Riot::Context.new("foo") {} } asserts("new assertions") do topic.asserts("nothing really") { true } end.kind_of(Riot::RR::Assertion) asserts("situation class") { topic.__send__(:situation_class) }.equals(Riot::RR::Situation) end # when using the RR context context "does not carry expectations between assertions" do setup do Riot::Context.new("foo") {} end helper(:situation) { Riot::RR::Situation.new } helper(:failing_assertion) { topic.asserts("I will fail") { mock!.a; mock!.b } } helper(:passing_assertion) { topic.asserts("I should not fail") { true } } asserts("first assertion fails") do failing_assertion.run(situation).first end.equals(:fail) asserts("second assertion passes") do passing_assertion.run(situation) end.equals([:pass, ""]) end # when using the RR context context "with RR doubles defined in setup" do setup do situation = Riot::RR::Situation.new situation.setup { mock!.hello } situation end asserts("an assertion") do Riot::RR::Assertion.new("test") { "foo" }.run(topic) end.equals([:fail, "hello() Called 0 times. Expected 1 times."]) asserts("another assertion won't use the expectations") do Riot::RR::Assertion.new("test") { "bar" }.run(topic) end.equals([:pass, ""]) end # with RR doubles defined in setup end # Riot with RR support riot-0.12.7/.gitignore0000644000004100000410000000012412261222026014566 0ustar www-datawww-data*.gem pkg .*.swp doc .yardoc *.tmproj _site *.watchr .DS_Store Gemfile.lock .rvmrc riot-0.12.7/.yardopts0000644000004100000410000000010412261222026014442 0ustar www-datawww-data-r README.markdown --protected --no-private - CHANGELOG MIT-LICENSE