Skip to content

Instantly share code, notes, and snippets.

@Qqwy
Created May 1, 2022 18:54
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save Qqwy/674d2382776cccb8870c47b4ab2cb727 to your computer and use it in GitHub Desktop.
Refined Minitest Assertions
class RefinedAssertions
@mutex = Mutex.new
def self.set_last_operator(operator, lhs, rhs, res)
@mutex.synchronize do
@set = true
@result = [operator, lhs, rhs, res]
end
end
def self.result
@mutex.synchronize do
@result
end
end
def self.set?
@mutex.synchronize do
@set
end
end
def self.unset
@mutex.synchronize do
@set = false
end
end
module ComparisonOperatorsPrepend
# NOTE: Cannot do =~ because it breaks in some dependency
MODULES = [:==, :!=, :<, :>, :<=, :>=, :is_a?, :<=>].map do |operator|
mod = Module.new do
define_method(operator) do |other|
res = super(other)
RefinedAssertions.set_last_operator(operator, self, other, res)
res
end
end
[operator, mod]
end.to_h
MODULES.each do |operator, mod|
Object.descendants.select { |d| d.method_defined?(operator) }.map do |descendant|
# puts "Prepending #{operator} to #{descendant}"
begin
descendant.prepend(mod)
rescue StandardError
end
end
end
end
end
module Minitest::Assertions
alias_method :orig_assert, :assert
def assert(test, msg = nil)
msg ||= proc do
if RefinedAssertions.set?
operator, lhs, rhs, result = RefinedAssertions.result
result_str = result.inspect
lhs_str = lhs.inspect
rhs_str = rhs.inspect
res = "Expected `#{lhs_str} #{operator} #{rhs_str}` to be truthy, was: #{result_str}."
if operator == :==
res += "\n" + diff(lhs, rhs)
end
RefinedAssertions.unset
res
end
end
orig_assert(test, msg)
end
alias_method :orig_refute, :refute
def refute(test, msg = nil)
msg ||= proc do
if RefinedAssertions.set?
operator, lhs, rhs, result = RefinedAssertions.res
res = "Expected `#{lhs.inspect} #{operator} #{rhs.inspect}` to not be truthy, was: #{result.inspect}."
RefinedAssertions.unset
res
end
end
orig_refute(test, msg)
end
end
@Qqwy
Copy link
Author

Qqwy commented May 1, 2022

This code allows syntax like

assert 1 <= 1.0

assert "hello" == "world"

On failure, it will print messages like

AuctionTest::test_some_test [SomeTest]:
Expected `"hello" == "world"` to be truthy, was: false.
Expected: "hello"
  Actual: "world"

It does so with somewhat of a dirty hack: Prepending custom overloaded operators to all existing classes that do what they normally do, but on top of that sets a global variable which can be read out by assert/refute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment