Git Product home page Git Product logo

wrong's Introduction

"Feels so right, it can't be Wrong"

Someone is Wrong on the Internet

Maintained by: Alex Chaffee http://alexchaffee.com

Abstract

Wrong provides a simple, general assert method that takes a block, and understands the code inside it, providing verbose failure messages for free.

The Wrong idea is to replace assert_equal and all those countless assert\_this, assert\_that, should\_something library methods which only exist to give a failure message that's not simply "assertion failed". Wrong replaces all of them in one fell swoop, since if you can write it in Ruby, Wrong can make a sensible failure message out of it.

We'd very much appreciate feedback and bug reports. There are plenty of things left to be done to make the results look uniformly clean and beautiful. We want your feedback, and especially to give us cases where either it blows up or the output is ugly or uninformative.

Inspired by assert { 2.0 } but rewritten from scratch. Compatible with Ruby (MRI) 1.8, 1.9, and JRuby 1.5.

Installation

gem install wrong

We have deployed gems for both Ruby and JRuby; if you get dependency issues on your platform, please let us know what Ruby interpreter and version you're using and what errors you get, and we'll try to track it down.

Usage

Wrong provides a simple assert method that takes a block:

require "wrong"   # or require "wrong/adapters/rspec" (see below)

include Wrong

assert { 1 == 1 }
 ==> nil

assert { 2 == 1 }
 ==> Expected (2 == 1), but 2 is not equal to 1

If your assertion is more than a simple predicate, then Wrong will split it into parts and show you the values of all the relevant subexpressions.

x = 7; y = 10; assert { x == 7 && y == 11 }
 ==>
Expected ((x == 7) and (y == 11)), but
    (x == 7) is true
    x is 7
    (y == 11) is false
    y is 10

--

age = 24
name = "Gaga"
assert { age >= 18 && ["Britney", "Snooki"].include?(name) }
 ==>
Expected ((age >= 18) and ["Britney", "Snooki"].include?(name)), but
    (age >= 18) is true
    age is 24
    ["Britney", "Snooki"].include?(name) is false
    name is "Gaga"

And a companion, 'deny':

deny{'abc'.include?('bc')}
 ==> Didn't expect "abc".include?("bc")

More examples are in the file examples.rb http://github.com/alexch/wrong/blob/master/examples.rb

There's also a spreadsheet showing a translation from Test::Unit and RSpec to Wrong, with notes, at this Google Doc. (Ask [email protected] if you want editing privileges.)

And don't miss the slideshare presentation.

Helper methods

All these helper methods are provided if you do include Wrong.

rescuing

There's also a convenience method for catching errors:

assert{ rescuing{raise "vanilla"}.message == "chocolate" }
 ==>
Expected (rescuing { raise("vanilla") }.message == "chocolate"), but
    rescuing { raise("vanilla") }.message is "vanilla"
    rescuing { raise("vanilla") } is #<RuntimeError: vanilla>
    raise("vanilla") raises RuntimeError: vanilla

capturing

And one for capturing output streams:

assert { capturing { puts "hi" } == "hi\n" }
assert { capturing(:stderr) { $stderr.puts "hi" } == "hi\n" }

out, err = capturing(:stdout, :stderr) { ... }
assert { out == "something standard\n" }
assert { err =~ /something erroneous/ }

close_to?

If you want to compare floats, try this:

assert { 5.0.close_to?(5.0001) }   # default tolerance = 0.001
assert { 5.0.close_to?(5.1, 0.5) } # optional tolerance parameter

If you don't want close_to? cluttering up Float in your test runs then use include Wrong::Assert instead of include Wrong.

close_to? also works on Times, Dates, and DateTimes. The default tolerance of 1 msec may be too small for you, so you might want to do something like:

assert { user.created_at.close_to?(Time.now, 2) }  # or 2.seconds

close_to? also works inside RSpec should statements with the magic be matcher, e.g.

5.should be_close_to(6)

d

We also implement the most amazing debugging method ever, d, which gives you a sort of mini-wrong wherever you want it , even in production code at runtime:

require 'wrong'
x = 7
d { x } # => prints "x is 7" to the console
d { x * 2 } # => prints "(x * 2) is 14" to the console
d("math is hard") { 2 + 2 } #=> prints "math is hard: (2 + 2) is 4"

d was originally implemented by Rob Sanheim in LogBuddy; as with Assert2 this version is a rewrite and homage. You may also enjoy g by jugyo.

Remember, if you want d to work at runtime (e.g. in a webapp) then you must include Wrong::D inside your app, e.g. in your environment.rb file.

eventually

If you care that something is going to be true soon, but maybe not right now, use eventually.

eventually { night? }

It will keep executing the block, up to 4 times a second, until either

  • the block returns true(ish)
  • 5 seconds elapse

If the block raises an exception, then eventually will treat that as a false and keep trying. The last time it fails, it'll raise that exception instead of a mere AssertionFailedError. That way, the following are all possible:

eventually { false }
eventually { assert { false } }
eventually { false.should be_true }  # in RSpec

and you should get the expected failure after time expires.

You can also send options to eventually as hash parameters.

eventually(:timeout => 10) { false } # keep trying for 10 sec
eventually(:delay => 1) { false }    # try every 1.0 sec, not every 0.25 sec

(For now, eventually is in its own module, but you get it when you include Wrong. Maybe it should be in Helpers like the rest?)

Test Framework Adapters

Adapters for various test frameworks sit under wrong/adapters.

Currently we support

  • Test::Unit - require 'wrong/adapters/test_unit'
  • Minitest - require 'wrong/adapters/minitest'
  • RSpec - require 'wrong/adapters/rspec' (now supports both 1.3 and 2.0)

To use these, put the appropriate require in your helper, after requiring your test framework; it should extend the framework enough that you can use assert { } in your test cases without extra fussing around.

For example:

require "test/unit"
require "wrong/adapters/test_unit"
class PlusTest < Test::Unit::TestCase
  def test_adding_two_and_two
    assert { 2 + 2 == 4 }
  end
end

require "rspec"
require "wrong/adapters/rspec"
describe "plus" do
  it "adds two and two" do
    assert { 2 + 2 == 4 }
  end
end

Piecemeal Usage

We know that sometimes you don't want all the little doodads from a library cluttering up your namespace. If you don't want to do

require 'wrong'
include Wrong

then you can instead require and include just the bits you really want. For example:

require 'wrong/assert'
include Wrong::Assert

will give you the assert and deny methods but not the formatters or rescuing or d or close_to?. And if all you want is d then do:

require 'wrong/d'
include Wrong::D

To summarize: if you do require 'wrong' and include Wrong then you will get the whole ball of wax. Most people will probably want this since it's easier, but there is an alternative, which is to require and include only what you want.

And beware: if you don't require 'wrong', then include Wrong will not do anything at all.

Gotcha: Side Effects Within the Assert Block

Be careful about making calls within the assert block that cause state changes.

@x = 1
def increment
  @x += 1
end

assert { increment == 2 }
assert { increment == 2 }
 ==> Expected (increment == 2), but
     increment is 5

The first time increment fires the result is 2. The second time the result is 3, and then Wrong introspects the block to create a good failure message, causing increment to fire a couple more times.

Confusing, we know! A few patient Wrong users have hit this when the assert involves ActiveRecord write methods like #create! and #save.

The fix: introduce a variable:

value = increment
assert { value == 2 }
assert { value == 2 }

Apology

So does the world need another assertion framework? In fact, it does not! We actually believe the world needs fewer assert methods.

The Wrong idea is to replace all those countless assert_this, assert_that, should_something library methods which only exist to give a more useful failure message than "assertion failed". Wrong replaces all of them in one fell swoop, since if you can write it in Ruby, Wrong can make a sensible failure message out of it.

Even the lowly workhorse assert_equal is bloated compared to Wrong: would you rather write this

assert_equal time, money

or this

assert { time == money }

? The Wrong way has the advantage of being plain, transparent Ruby code, not an awkward DSL that moves "equal" out of its natural place between the comparands. Plus, WYSIWYG! You know just from looking at it that "equal" means ==, not eql? or === or =~.

Moreover, much like TDD itself, Wrong encourages you to write cleaner code. If your assertion messages are not clear and "Englishy", then maybe it's time for you to refactor a bit -- extract an informatively named variable or method, maybe push some function onto its natural object a la the Law of Demeter... Also, try not to call any methods with side effects inside an assert. In addition to being bad form, this can cause messed-up failure messages, since the side effects may occur several times in the process of building the message.

Wrong also lets you put the expected and actual values in any order you want! Consider the failure messages for

assert { current_user == "joe" } # => Expected (current_user == "joe") but current_user is "fred"
assert { "joe" == current_user } # => Expected ("joe" == current_user) but current_user is "fred"

You get all the information you want, and none you don't want. At least, that's the plan! :-)

BDD with Wrong

Wrong is compatible with RSpec and MiniTest::Spec, and probably Cucumber too, so you can use it inside your BDD framework of choice. To make your test code even BDD-er, try aliasing assert to either should or (Alex's favorite) expect.

Here's an RSpec example:

require "wrong/adapters/rspec"
Wrong.config.alias_assert :expect, override: true

describe BleuCheese do
  it "stinks" do
    cheese = BleuCheese.new
    expect { cheese.smell > 9000 }
  end
end

This makes your code read like a BDD-style DSL, without RSpec's "should" syntax (which is, let's face it, pretty weird the first few hundred times you have to use it). Compare

expect { cheese.smell > 9000 }

to

cheese.smell.should be > 9000

and consider which one more clearly describes the desired behavior. The object under test doesn't really have a should method, so why should it magically get one during a test?

Warning: currently the use of alias_assert :expect is not compatible with RSpec, since RSpec also defines expect as a synonym for lambda. If you really want to use expect as an alias form assert, then use Wrong.config.alias_assert :expect, :override => true. See issue #6 for more details.

Algorithm

So wait a second. How do we do it? Doesn't Ruby have poor support for AST introspection? Well, yes, it does, so we cheat: we figure out what file and line the assert block is defined in, then open the file, read the code, and parse it directly using Ryan Davis' amazing RubyParser and Ruby2Ruby. You can bask in the kludge by examining chunk.rb and assert.rb. If you find some code it can't parse, please send it our way.

Before you get your knickers in a twist about how this is totally unacceptable because it doesn't support this or that use case, here are our caveats and excuses:

  • It works! Tested in MRI 1.8.6, 1.8.7, 1.9.1, 1.9.2, 1.9.3, and JRuby 1.5.3. (Thank you, rvm!)
  • Your code needs to be in a file.
    • If you're developing Ruby code without saving it to a mounted disk, then sorry, Wrong is not right for you.
    • We monkey-patch IRB so if you do irb -rwrong it'll save off your session in memory where Wrong can read it.
    • It'd be nice if it could work inside a -e block but as far as we can tell, there's no way to grab that -e source code from inside Ruby.
  • It's a development-time testing library, not a production runtime library, so there are no security or filesystem issues.
  • eval isn't evil, it's just misunderstood.
  • It makes a few assumptions about the structure of your code, leading to some restrictions:
    • You can't have more than one call to assert per line. (This should not be a problem since even if you're nesting asserts for some bizarre reason, we assume you know where your Return key is.)
    • You can't use metaprogramming to write your assert blocks.
    • All variables and methods must be available in the binding of the assert block.
    • Passing a proc around and eventually calling assert on it might not work in some Ruby implementations.
  • Beware of Side Effects! (See discussion elsewhere in this document.)
  • "Doesn't all this parsing slow down my test run"? No - this applies to failure cases only. If the assert block returns true then Wrong simply moves on.

FYI, the method_source gem uses a similar algorithm (keep grabbing lines of source code and try to parse them until you stop getting parse errors).

Explanations

assert and deny can take an optional explanation, e.g.

  assert("since we're on Earth") { sky.blue? }

Since the point of Wrong is to make asserts self-explanatory, you should use explanations only when they would add something that you couldn't get from reading the (failed) assertion code itself. Don't bother doing things like this:

  assert("the sky should be blue") { sky.blue? } # redundant

The failure message of the above would be something like "Expected sky.blue? but sky is :green" which is not made clearer by the addition of "the sky should be blue". We already know it should be blue since we see right there ("Expected (sky.blue?)") that we're expecting it to be blue.

And if your assertion code isn't self-explanatory, then that's a hint that you might need to do some refactoring until it is. (Yes, even test code should be clean as a whistle. Especially test code.)

Details

When a failure occurs, the exception message contains all the details you might need to make sense of it. Here's the breakdown:

Expected [CLAIM], but
  [FORMATTER]
  [SUBEXP] is [VALUE]
  ...
  • CLAIM is the code inside your assert block, normalized
  • If there is a formatter registered for this type of predicate, its output will come next. (See below.)
  • SUBEXP is each of the subtrees of the claim, minus duplicates and truisms (e.g. literals).
  • The word "is" is a very nice separator since it doesn't look like code, but is short enough to be easily visually parsed.
  • VALUE is eval(SUBEXP).inspect, wrapped and indented if necessary to fit your console

We hope this structure lets your eyes focus on the meaningful values and differences in the message, rather than glossing over with stack-trace burnout. If you have any suggestions on how to improve it, please share them.

(Why does VALUE use inspect and not to_s? Because inspect on standard objects like String and Array are sure to show all relevant details, such as white space, in a console-safe way, and we hope other libraries follow suit. Also, to_s often inserts line breaks and that messes up formatting and legibility.)

Wrong tries to maintain indentation to improve readability. If the inspected VALUE contains newlines, or is longer than will fit on your console, the succeeding lines will be indented to a pleasant level.

Sometimes Wrong will not be able to evaluate a detail without raising an exception. This exception will be duly noted, which might be misleading. For example,

a = [1,2,3,4]
assert { a.all? {|i| i<4} }

would fail, since on the final pass, (i < 4) is false. But the error message is a bit vague:

Wrong::Assert::AssertionFailedError: Expected a.all? { |i| (i < 4) }, but
    i raises NameError: undefined local variable or method `i' for main:Object

In evaluating the inner expression, Wrong does not have access to the block parameter i, since i is not in the scope of the outer expression. A better way to write the assertion would be

a = [1,2,3,4]
a.each {|i| assert {i < 4}}

which gives

Wrong::Assert::AssertionFailedError: Expected (i < 4), but
    i is 4

Formatters

Enhancements for error messages sit under wrong/message.

Currently we support special messages for

  • String ==
  • Array(ish) ==
    • including nested string elements

To use the Array formatter, you may also need to gem install diff-lcs (it's an optional dependency).

require "wrong/message/string_comparison"
assert { "the quick brown fox jumped over the lazy dog" ==
         "the quick brown hamster jumped over the lazy gerbil" }
 ==>
Expected ("the quick brown fox jumped over the lazy dog" == "the quick brown hamster jumped over the lazy gerbil"), but
Strings differ at position 16:
 first: ..."quick brown fox jumped over the lazy dog"
second: ..."quick brown hamster jumped over the lazy gerbil"

require "wrong/message/array_diff"
assert { ["venus", "mars", "pluto", "saturn"] ==
         ["venus", "earth", "pluto", "neptune"] }
 ==>
Expected (["venus", "mars", "pluto", "saturn"] == ["venus", "earth", "pluto", "neptune"]), but ["venus", "mars", "pluto", "saturn"] is not equal to ["venus", "earth", "pluto", "neptune"]

array diff:
["venus", "mars" , "pluto", "saturn" ]
["venus", "earth", "pluto", "neptune"]
          ^                 ^

Config

These settings can either be set at runtime on the Wrong.config singleton, or inside a .wrong file in the current directory or a parent. In the .wrong file just pretend every line is preceded with Wrong.config. -- e.g. if there's a setting called ice_cream, you can do any of these in your .wrong file

ice_cream                           # => Wrong.config[:ice_cream] => true
ice_cream = true                    # => Wrong.config[:ice_cream] => true
ice_cream = "vanilla"               # => Wrong.config[:ice_cream] => "vanilla"

or any of these at runtime:

Wrong.config.ice_cream              # => Wrong.config[:ice_cream] => true
Wrong.config.ice_cream = true       # => Wrong.config[:ice_cream] => true
Wrong.config.ice_cream = "vanilla"  # => Wrong.config[:ice_cream] => "vanilla"

Color

Apparently, no test framework is successful unless and until it supports console colors. Call

Wrong.config.color

in your test helper or rakefile or wherever, or put

color

in your .wrong file and get ready to be bedazzled. If you need custom colors, let us know.

Aliases

An end to the language wars! Name your "assert" and "deny" methods anything you want.

  • In your code, use Wrong.config.alias_assert and Wrong.config.alias_deny
  • In your .wrong file, put alias_assert :expect on a line by itself

Here are some suggestions:

alias_assert :expect # warning: not compatible with RSpec
alias_assert :should # This looks nice in RSpec
alias_assert :confirm
alias_assert :be

alias_assert :is
alias_deny :aint

alias_assert :assure
alias_deny :refute

alias_assert :yep
alias_deny :nope

alias_assert :yay!
alias_deny :boo!

Just don't use "aver" since we took that one for an internal method in Wrong::Assert.

Verbose

Wrong works inside frameworks like Test::Unit and RSpec, but sometimes you just want to stick a bunch of assertions in a file and run it. In that case, verbose mode might come in handy. It prints every successful assertion to the console (including explanations, if provided, and in color, if desired).

Wrong.config.verbose
assert("basic math") { 2 + 2 == 4}

prints

basic math: ((2 + 2) == 4)

Helper Assert Methods

If you really want to, you can define your proc in one method, pass it in to another method, and have that method assert it. This is a challenge for Wrong and you probably shouldn't do it. Wrong will do its best to figure out where the actual assertion code is but it might not succeed.

If you're in Ruby 1.8, you really shouldn't do it! But if you do, you can use the "depth" parameter to give Wrong a better hint about how far up the stack it should crawl to find the code. See assert_test.rb for more details, if you dare.

Authors

Bugs

todo

Etc

wrong's People

Contributors

alexch avatar amatsuda avatar jfirebaugh avatar mpasternacki avatar sconover avatar thenrio avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wrong's Issues

assert's failures count as errors

Hi again.

Using Ruby 1.8.7 and test/unit running this file:

require 'rubygems'
require 'test/unit'
require 'wrong'

class WrongTest < Test::Unit::TestCase
  include Wrong
  def test_something
    assert { false }
  end
end

Gives me this output:

Loaded suite wrong_test
Started
E
Finished in 0.003617 seconds.

  1) Error:
test_something(WrongTest):  
Wrong::Assert::AssertionFailedError: Expected false
    /Users/minciue/.rvm/gems/ree-1.8.7-2011.03/gems/wrong-0.5.0/lib/wrong/assert.rb:68:in `aver'
    /Users/minciue/.rvm/gems/ree-1.8.7-2011.03/gems/wrong-0.5.0/lib/wrong/assert.rb:34:in `assert'
    wrong_test.rb:8:in `test_something'

1 tests, 0 assertions, 0 failures, 1 errors

Thank you.

wrong assertions don't show up in count

Hello. With test/unit and Ruby 1.8.7 (I can be more specific if that matters), wrong's assert { } calls don't show up in the assertion counts. Running the following file

require 'rubygems'
require 'test/unit'
require 'wrong'

class WrongTest < Test::Unit::TestCase
  include Wrong
  def test_something
    puts 'tested something'
    assert { true }
  end
end

Gives me this output:

Loaded suite wrong_test
Started
tested something
.
Finished in 0.000497 seconds.

1 tests, 0 assertions, 0 failures, 0 errors

I'm not too familiar with Test/Unit internals but with a pointer in the right direction I can probably write you a fix for this.

Oh, and thanks for this gem, I'm really loving it so far.

Wrong::Config.read_here_or_higher can't handle absolute paths

read_here_or_higher doesn't expect its first argument to be an absolute path, which, on Windows, leads to inability to retrieve an assertion's source if it is located in a file other than the program's entry point.

The easiest way to reproduce is to create a file containing the following:

require 'wrong'
include Wrong::Assert
assert{false}

and then require it from irb. On Windows, instead of "Expected false (Wrong::Assert::AssertionFailedError)" you get "[couldn't retrieve source code due to #<Errno::EINVAL: Invalid argument - ./c:/absolute/path/to/your/file.rb>]"

Fails to handle Ranges

require 'wrong'
include Wrong
assert{(1..2) == (1..1)}

produces a NoMethodError instead of the usual description (tested on ruby 2.1 and 1.9.3)

Endless warnings about uninitialized variable

Hi, I run my tests with warnings enabled, and each test outputs:

[...]/wrong-0.5.4/lib/wrong/assert.rb:23: warning: instance variable @_inside_wrong_assert not initialized

Adding the following just before the offending line solves this:

@_inside_wrong_assert ||= false

wrong causes assert_select to fail

I am using rspec with wrong in a rails app. I have the followin in my spec_helper.rb file:

require "wrong/adapters/rspec"
Wrong.config.alias_assert :confirm

However, when I used assert_select, eg:

  assert_select 'tbody > tr', count: 4

I get the error:

RuntimeError: You must pass a block to Wrong's assert and deny methods

The exception is thrown from

~/.rvm/gems/ruby-1.9.3-p125/gems/actionpack-3.2.9/lib/action_dispatch/testing/assertions/selector.rb

on line 297:

assert matches.size >= min, message if min

It seems wrong is taking over Test::Unit's assert function, causing the function to crash. The alias_assert also doesn't help, since it just aliases the method - the assert method is still there.

I am currently using the following as a workaround:

obj = Object.new
class << obj
  include Test::Unit::Assertions
end
Wrong::Assert.send(:define_method, :assert) do |*args, &block|
  obj.assert(*args, &block)
end

It works, but it would be nice if a better solution was available.

shrink virtual line size when inside rspec

RSpec indents when printing the exception message, which means that the line should wrap 8 characters (or so) sooner than it does now. Probably the same for other test frameworks too.

Puzzling behavior with eventually and rspec be_nil matcher

I found an odd behavior when using eventually and should_not be_nil.

it "should work with be_nil" do
    found = "X"
    eventually {
      found.should_not be_nil
    }
end

Error message is:

Expected found.should_not(be_nil), but
found is "X"
be_nil is #<RSpec::Matchers::BuiltIn::BeNil:0x007ff531aea8e8
@expected=nil>

Am I doing anything wrong?

Misleading output when variables inside assert block have gone out of scope

This is closely related to #21.

In his comment on that issue, @alexch pointed out that variables inside an assert block might be out of scope when the gem tries to introspect them. This can make for misleading output. An example using Test::Unit:

  test "wrong block example" do
    assert do
      (1..5).all? do |num|
        num.in? 1..4
      end
    end
  end

This test fails with the following output:

===============================================================================
Failure:
  Expected (1..5).all? { |num| num.in?((1..4)) }, but
      num.in?((1..4)) raises NameError: undefined local variable or method `num' for test_wrong_block_example(WorkShelfTest):WorkShelfTest
      num raises NameError: undefined local variable or method `num' for test_wrong_block_example(WorkShelfTest):WorkShelfTest
      (1..4) is 1..4
test_wrong_block_example(WorkShelfTest)
test/unit/work_shelf_test.rb:7:in `block in <class:WorkShelfTest>'
===============================================================================

A test failure like this had me scratching my head for several minutes today, because I couldn't see how num could possibly be undefined.

Perhaps the solution is not to report such NameErrors in test output? If a real NameError exception were being generated by the code inside the assert block, we could rely on the test framework to report that exception, right?

Doesn't produce the expected output

I tried the first example in the README on Ruby 2.1.4p265, and it doesn't produce the output I expected from the description in the README. The code sample is the following:

require 'wrong'

include Wrong

assert { 1 == 1 }

assert { 2 == 1 }

It produces the following output:

/Users/moonglum/.rvm/gems/ruby-2.1.4/gems/wrong-0.7.1/lib/wrong/assert.rb:82:in `aver': Expected (2 == 1) (Wrong::Assert::AssertionFailedError)
        from /Users/moonglum/.rvm/gems/ruby-2.1.4/gems/wrong-0.7.1/lib/wrong/assert.rb:34:in `assert'
        from test.rb:7:in `<main>'

I would expect an output like this:

 ==> Expected (2 == 1), but 2 is not equal to 1

I'm using wrong 0.7.1 freshly installed from RubyGems. Commenting out the last line doesn't give me any output at all.

sexp_processor 4.0 gemspecs incompatibility

Running bundler with a command like: bundle outdated

I am starting to get this ( since June 7th when sexp_processor got upgraded to version 4 ).

Bundler could not find compatible versions for gem "sexp_processor":
In Gemfile:
wrong (>= 0.6.2) ruby depends on
sexp_processor (~> 3.0) ruby

wrong (>= 0.6.2) ruby depends on
  sexp_processor (4.0.0)

Add missing tags

Would be great to see missing tags/releases for the corresponding gem files here, too.

Integration bug with RSpec: can't alias :expect, :assert

The README says you can alias assert with expect when using RSpec. This actually doesn't work because rspec-expectations already defines expect (as an alias for lambda). The outcome is that all examples pass whether they should or not.

RSpec recently added a hook to configure the assertion/expectation library to be either rspec-expectations, stdlib (t/u assertions on 1.8, minitest assertion on 1.9), or both. I tried setting this to use stdlib so rspec-expectations wouldn't be loaded (and define expect, but then there were errors because wrong assigns failure_class the value RSpec::Expectations::ExpectationNotMetError, which lives (as its name suggests) in rspec-expectations.

Since this isn' t working as advertised, it'd be great if you changed the README to exclude the bit about aliasing assert with expect.

Once that's done, I'd like to get this working and am happy to collaborate with you to do so. The question is what belongs where? One possibility is for RSpec to expose a configuration option that turns off the lambda, expect alias. Another is for RSpec to expose a better extension point for this sort of integration - something like the mock framework adapters. I'm sure there are several other approaches we could take.

WDYT?

Inaccurate rspec dis in the README

From the wrong README:

And in what human language is "should greater than" a valid phrase?

It's not in human languages, or RSpec. The correct use of ">" is:

BleuCheese.new.smell.should be > 9000

You may still prefer assert { BleuCheese.new.smell > 9000 }, but at least you're preferring it over the right thing.

FWIW, what's in the wrong README will work, but that's only to support people who don't bother to RTFM: http://rubydoc.info/gems/rspec-expectations#Comparisons

Bump gem version

#30 is needed to work with cucumber. It's merged into master, but a new version hasn't been released.

Doesn't work with enumerables

a = [1,2,3,4]

assert{a.all?{|i| i<4}}

Wrong::Assert::AssertionFailedError: Expected a.all? { |i| (i < 4) }, but
    i raises NameError: undefined local variable or method `i' for main:Object

    from /Users/bradphelan/.rvm/gems/ruby-1.9.2-p180/gems/wrong-0.5.4/lib/wrong/assert.rb:72:in `aver'
    from /Users/bradphelan/.rvm/gems/ruby-1.9.2-p180/gems/wrong-0.5.4/lib/wrong/assert.rb:34:in `assert'
    from (irb):12
    from /Users/bradphelan/.rvm/rubies/ruby-1.9.2-p180/bin/irb:16:in `<main>'

also

 assert{a.all?{|i| i<4}==true}
Wrong::Assert::AssertionFailedError: Expected a.all? { |i| (i < 4) }, but
    i raises NameError: undefined local variable or method `i' for main:Object

    from /Users/bradphelan/.rvm/gems/ruby-1.9.2-p180/gems/wrong-0.5.4/lib/wrong/assert.rb:72:in `aver'
    from /Users/bradphelan/.rvm/gems/ruby-1.9.2-p180/gems/wrong-0.5.4/lib/wrong/assert.rb:34:in `assert'
    from (irb):12
    from /Users/bradphelan/.rvm/rubies/ruby-1.9.2-p180/bin/irb:16:in `<main>'

Wrong + Zeus

When I execute an rspec test with zeus and it contains an "assert" block, the ruby process's cpu usage skyrockets to 100% and it drops into an infinite loop. When I execute the same test with pure rspec everything works fine.

Project name feels wrong - can't google it :(

Hi Steve,

Having written assert_* and should bla for 12 years, I was quite curious about the "Wrong" way. So far, so good:)

Googling "wrong" related articles is difficult, would you change the name?
Something more googable like Wronga, wrongwrong, wrong-assertions, ...

Cheers,

Jean-Michel

NameError on otherwise un-referenced block arg in failing example

Given the following failing example in failing_example.rb

require 'wrong/adapters/rspec'

describe "a block arg in a failing assertion" do
  it "raises a NameError :(" do
    assert { [].each {|v|} != [] }
  end
end

When I run rspec failing_example.rb

Then I get this error:

F

Failures:

  1) a block arg in a failing assertion raises a NameError :(
     Failure/Error: assert { [].each {|v|} != [] }
       Expected [].each { |v| }.!=([]), but
           (v) raises NameError: undefined local variable or method `v' for #<RSpec::Core::ExampleGroup::Nested_1:0x007f938a0d1ef0>
     # ./failing_example.rb:5:in `block (2 levels) in <top (required)>'

The example should fail, that's not the problem. The problem is the failure message should indicate that the values were not equal, not a NameError on v

conflicts with minitest in Rails 4 and rspec_rails

In Rails 4 with rspec_rails, my assert method is from minitest, not from wrong.

Here's an app demonstrating the problem: https://github.com/jjb/rails_4_rspec_rails_wrong

Here's the relevant commit: jjb/rails_4_rspec_rails_wrong@c59d8f4

I tried putting require 'wrong/adapters/minitest' above and below the rspec require in spec_helper, it made no difference.

rspec_rails does all these handy matcher delegations, maybe that contributes to the problem?

I didn't try a pure-rspec experiment. Let me know if you are at a loss and I will try that.

License missing from gemspec

RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.

via e.g.

  spec.license = 'MIT'
  # or
  spec.licenses = ['MIT', 'GPL-2']

Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can imagine, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.

There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!

Appendix:

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies

p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post about this project for more information.

uninitialized constant Wrong::Date

I installed wrong to win an argument (and I won), but I couldn't run it...

$ ruby2.5 test_me.rb 
Traceback (most recent call last):
	11: from test_me.rb:2:in `<main>'
	10: from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:39:in `require'
	 9: from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:135:in `rescue in require'
	 8: from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:135:in `require'
	 7: from /var/lib/gems/2.5.0/gems/wrong-0.7.1/lib/wrong.rb:6:in `<top (required)>'
	 6: from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	 5: from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	 4: from /var/lib/gems/2.5.0/gems/wrong-0.7.1/lib/wrong/helpers.rb:5:in `<top (required)>'
	 3: from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	 2: from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	 1: from /var/lib/gems/2.5.0/gems/wrong-0.7.1/lib/wrong/close_to.rb:1:in `<top (required)>'
/var/lib/gems/2.5.0/gems/wrong-0.7.1/lib/wrong/close_to.rb:12:in `<module:Wrong>': uninitialized constant Wrong::Date (NameError)
Did you mean?  Data

ruby 2.5.5p157 on Raspbian and ruby 2.5.1p57 on Ubuntu both have the same problem.

Test::Unit assertion count does not include wrong assertions

I have a test file that is comprised entirely of wrong assertions (wrong_wrong.rb):

require 'active_support'
require 'wrong'

class WrongWrongTest < ActiveSupport::TestCase
  include Wrong

  def test_if_wrong_is_right
    assert{ true }
  end

  def test_if_wrong_is_right_about_being_wrong
    assert{ false }
  end
end

I run the tests:

~/tmp $ testrb wrong_wrong.rb
Loaded suite WrongWrongTest
Started
E

Error:
test_if_wrong_is_right_about_being_wrong(WrongWrongTest):
Wrong::Assert::AssertionFailedError: Expected false
    /Users/barry/.rvm/gems/ree-1.8.7-2010.02/gems/wrong-0.6.0/lib/wrong/assert.rb:72:in `aver'
    /Users/barry/.rvm/gems/ree-1.8.7-2010.02/gems/wrong-0.6.0/lib/wrong/assert.rb:34:in `assert'
    /Users/barry/tmp/wrong_wrong.rb:12:in `test_if_wrong_is_right_about_being_wrong'
    /Users/barry/.rvm/gems/ree-1.8.7-2010.02/gems/activesupport-3.1.0/lib/active_support/testing/setup_and_teardown.rb:67:in `__send__'
    /Users/barry/.rvm/gems/ree-1.8.7-2010.02/gems/activesupport-3.1.0/lib/active_support/testing/setup_and_teardown.rb:67:in `run'
    /Users/barry/.rvm/gems/ree-1.8.7-2010.02/gems/activesupport-3.1.0/lib/active_support/callbacks.rb:390:in `_run_setup_callbacks'
    /Users/barry/.rvm/gems/ree-1.8.7-2010.02/gems/activesupport-3.1.0/lib/active_support/callbacks.rb:81:in `send'
    /Users/barry/.rvm/gems/ree-1.8.7-2010.02/gems/activesupport-3.1.0/lib/active_support/callbacks.rb:81:in `run_callbacks'
    /Users/barry/.rvm/gems/ree-1.8.7-2010.02/gems/activesupport-3.1.0/lib/active_support/testing/setup_and_teardown.rb:65:in `run'



Finished in 0.005216 seconds.

2 tests, 0 assertions, 0 failures, 1 errors, 0 pendings, 0 omissions, 0 notifications
0% passed

383.44 tests/s, 0.00 assertions/s

Notice how the one failure shows in the results as 1 errors. But the successful assertion does not show, rather 0 assertions.

System info:

~/tmp $ gem list | grep wrong
wrong (0.6.0, 0.5.6, 0.5.4, 0.5.0, 0.4.5)
~/tmp $ gem list | grep test-unit
test-unit (2.4.0, 2.3.2, 2.2.0, 2.1.2, 1.2.3)
~/tmp $ gem list | grep activesupport
activesupport (3.1.0, 3.0.10, 3.0.6, 3.0.5, 3.0.4, 3.0.3, 3.0.1, 3.0.0, 3.0.0.rc, 2.3.8, 2.3.5)

Am I nuts?

parse the last line of the block only on failure????

So I have this kinda crazy idea for integrating wrong with rspec:

describe User do
  it "has the read-only role by default" do
    User.new.role == Role::READ_ONLY
  end
end

The idea is that, if configured to do so, rspec would forward the block passed to it to assert (or maybe wrong could expose a function to support similar w/o having to include anything). This way you don't even need to fuss over "assert" v "expect" - the block passed to it has to conform to the same rules as a block passed to wrong's assert.

As a preliminary experiment, I tried this:

require 'wrong/adapters/rspec'

describe "something" do
  it "does something" do
    assert do
      x = 5
      y = 3
      x == y
    end
  end

  it "does something else" do
    x = 5
    y = 3
    assert { x == y }
  end
end

When I ran this I got the following output:

FF

Failures:

  1) something does something
     Failure/Error: assert do
       Expected x = 5
       y = 3
       (x == y)
       , but
           (x == y) raises NameError: undefined local variable or method `x' for #<RSpec::Core::ExampleGroup::Nested_1:0x007fe41bdd35e0>
           x raises NameError: undefined local variable or method `x' for #<RSpec::Core::ExampleGroup::Nested_1:0x007fe41bdd35e0>
           y raises NoMethodError: undefined method `yaml' for nil:NilClass
     # ./example_spec.rb:5:in `block (2 levels) in <top (required)>'

  2) something does something else
     Failure/Error: assert { x == y }
       Expected (x == y), but
           x is 5
           y is 3
     # ./example_spec.rb:15:in `block (2 levels) in <top (required)>'

As you can see, wrong does a great job of providing feedback for the example with the single line block, but the feedback for the multi-line block is a bit useless. So the question is: can wrong be modified to only care about the last statement in the block? Of course, the other question is: do you think this idea is interesting enough to try to make it happen?

Failure to correctly dis RSpec in your docs

Hey y'all - if you're going to dis another library to make yours look good, at least get the syntax of the other lib correct.

BlueCheese.new.smell.should be > 9000

Cheers,
David

NameError when trying to debug in RubyMine

Requiring Wrong and starting debug in RubyMine produces NameError:

undefined method `evaluate' for class `IRB::Context' (NameError)

Stacktrace:

/Users/***/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/wrong-0.7.1/lib/wrong/irb.rb:4:in `<class:Context>'
/Users/***/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/wrong-0.7.1/lib/wrong/irb.rb:3:in `<module:IRB>'
/Users/***/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/wrong-0.7.1/lib/wrong/irb.rb:2:in `<top (required)>'
/Users/***/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/wrong-0.7.1/lib/wrong.rb:12:in `require'
/Users/***/.rbenv/versions/2.3.2/lib/ruby/gems/2.3.0/gems/wrong-0.7.1/lib/wrong.rb:12:in `<top (required)>'
/Users/***/*/file.rb:10:in `require'

So it blocks debugging completely.

Including Wrong in a Rails App

I'm having issues including Wrong in a trivial greenfield test application. Though this is more "support" than "issue", I'm guessing whatever the right answer is means the docs need updating.

First, get set up:

$ rails -v
Rails 3.2.3
$ rails new test_app
$ cd test_app/
$ rake db:create
$ rails g scaffold Post title:string body:text
$ rake db:migrate

This will give you a trivial new app with some tests to run:

$ rake test:functionals
Run options: 

# Running tests:

.......

Finished tests in 0.154397s, 45.3377 tests/s, 64.7681 assertions/s.

7 tests, 10 assertions, 0 failures, 0 errors, 0 skips

Okay, great. Now add gem "wrong" to the Gemfile, and bundle install.

Then, add wrong to your test/test_helper.rb file like so: https://gist.github.com/61af0b2b0431e61c1258

Crack open your test/functional/posts_controller_test.rb and add two trivial wrong-style assertions: https://gist.github.com/e75c14cf155e5decdf22

Now run your tests and enjoy your errors:

$ rake test:functionals

# Running tests:

...EE..

Finished tests in 0.160737s, 43.5494 tests/s, 62.2134 assertions/s.

  1) Error:
test_should_get_index(PostsControllerTest):
ArgumentError: wrong number of arguments (0 for 1)
[...]

  2) Error:
test_should_get_new(PostsControllerTest):
ArgumentError: wrong number of arguments (0 for 1)
[...]

7 tests, 10 assertions, 0 failures, 2 errors, 0 skips

The suite is seemingly still trying to use MiniTest's assert, which takes 1 argument.

Thoughts?

wrong takes over `expect`... unexpectedly

I have this spec:

it "should create Foo" do
  expect{
    post :create, foo: {owner_id: 1, bar_id: 1}
  }.to change(Foo, :count)
  expect(assigns(:foo).owner_id).to eq(1)
  expect(assigns(:foo).bar_id).to eq(1)
  expect(response).to redirect_to(root_path)
end

Run with everything but the last line, it succeeds. But with the last line, this happens:

1) FoosController should create group ownership
   Failure/Error: expect(response).to redirect_to(root_path)
   RuntimeError:
     You must pass a block to Wrong's assert and deny methods
   # /Users/john/src/wrong/lib/wrong/assert.rb:31:in `rescue in assert'
   # /Users/john/src/wrong/lib/wrong/assert.rb:27:in `assert'
   # ./spec/controllers/foos_controller_spec.rb:9:in `block (2 levels) in <top (required)>'

It's as if alias_assert :expect is being invoked, but just for that one spec.

I've experimented with different combinations and orderings and determined that the problem only happens when redirect_to is present.

Any ideas?

Rails 4.1/Rspec-rails 2.99 broken

Using Rails 4.1 (maybe also 4.0) and Rspec-rails 2.99, the assert method does not work.

ArgumentError:
       wrong number of arguments (0 for 1..2)

I used this fix:

if RSpec.const_defined? :Rails
  require 'rails/version'
  if Rails::VERSION::MAJOR == 4
    module RSpec::Rails::MinitestAssertionAdapter::ClassMethods
      def define_assertion_delegators_with_removed
        define_assertion_delegators_without_removed
        class_eval do
          remove_method :assert
        end
      end
      alias_method_chain :define_assertion_delegators, :removed
    end
  end

in addition to the RAILS::VERSION::MAJOR == 3 part in https://github.com/sconover/wrong/blob/master/lib/wrong/adapters/rspec.rb#L7

Just changing the == 3 to >=3 did not work because:

gems/activesupport-4.1.0.beta1/lib/active_support/concern.rb:126:in `included': 
Cannot define multiple 'included' blocks for a Concern (ActiveSupport::Concern::MultipleIncludedBlocks)

This is, why I used the alias method chain.

Cannot install 'wrong' gem because of sexp_processor dependency

After having built the gem with the command:

  • gem build wrong.gemspec
    I tried to install it with the command:
  • gem install wrong-0.6.3.gem
    but I got the following error:
  • ERROR: While executing gem ... (Gem::DependencyError)
    Unable to resolve dependencies: wrong requires sexp_processor (>= 4.0); sourcify requires sexp_processor (>= 3.0.5); ParseTree requires sexp_processor (> 3.2.0); ruby2ruby requires sexp_processor (> 4.0); ruby_parser requires sexp_processor (~> 4.1)

The dependencies on sexp_processor don't seem can all be satisfied, as ParseTree dependes on a version which can't satisfy all the others.

My environment is:
Windows 7 64bit, Ruby 1.9.3

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.