Skip to content

Instantly share code, notes, and snippets.

@wojtekmach
Last active August 29, 2015 14:18
Show Gist options
  • Save wojtekmach/3e349a5a62f9cb1aac12 to your computer and use it in GitHub Desktop.
Save wojtekmach/3e349a5a62f9cb1aac12 to your computer and use it in GitHub Desktop.
# Sometimes, especially when working with JSON APIs,
# when testing I found myself wanting to test the "shape" of data and
# only some particular elements, rather than either:
#
# 1. test everything - which is tricky with things like auto_increment primary keys,
# created_at fields etc
# 2. test only subset of data - do stuff like:
# `JSON(response.body).map { |h| h['name'] }.should == ['Item 1', 'Item 2']
#
# Here, I want to try something different. See:
# `test_why_someone_would_ever_use_it`
require 'minitest/autorun'
require 'securerandom'
require 'set'
require 'date'
module Anything; end
class AnythingTest < Minitest::Test
include Anything
def test_why_someone_would_ever_use_it
people = [
[SecureRandom.uuid, Time.now, "Alice"],
[SecureRandom.uuid, Time.now + 10, "Bob"],
]
uuid = any_unique ^ string_of_length(36)
assert_equal [
[uuid, any_time, "Alice"],
[uuid, any_time, "Bob"],
], people
end
def test_anything
assert_equal anything, 42
assert_equal anything, anything
assert_equal anything, nil
skip
assert_equal nil, anything
end
def test_any_integer
assert_equal any_integer, 42
refute_equal any_integer, "foo"
refute_equal any_integer, 1.0
refute_equal "foo", any_integer
end
def test_any_number
assert_equal any_number, 42
assert_equal any_number, 42.0
refute_equal "foo", any_number
end
def test_any_string
assert_equal any_string, "foo"
refute_equal any_string, 42
end
def test_string_of_length
assert_equal string_of_length(3), "foo"
refute_equal string_of_length(5), "foo"
end
def test_upcase_string
assert_equal upcase_string, "FOO"
refute_equal upcase_string, "Foo"
end
def test_composition
three_letter_upcase = string_of_length(3) ^ upcase_string
assert_equal three_letter_upcase, "FOO"
refute_equal three_letter_upcase, "FOOFOO"
refute_equal three_letter_upcase, "foo"
end
def test_composition_composition
starts_with_n = Class.new(AnyString) {
def ==(o)
o.start_with?("n") || o.start_with?("N")
end
}.new
acronym = string_of_length(3) ^ upcase_string ^ starts_with_n
assert_equal acronym, "NBA"
assert_equal acronym, "NSA"
refute_equal acronym, "FBI"
refute_equal acronym, "NASA"
refute_equal acronym, "nba"
end
def test_sorted_array
assert_equal sorted_array, [1, 2, 3]
refute_equal sorted_array, [3, 2, 1]
end
def test_even_number
assert_equal even_number, 2
refute_equal even_number, 1
end
def test_odd_number
assert_equal odd_number, 1
refute_equal odd_number, 2
end
# AnyUnique is probably a terrible idea
def test_any_unique
assert_equal any_unique, 1
assert_equal any_unique, 2
end
def test_any_unique_failure
assert_equal any_unique, 1
refute_equal any_unique, 1
end
def test_any_unique_composition
unique_string = any_unique ^ any_string
assert_equal unique_string, "a"
assert_equal unique_string, "b"
assert_equal unique_string, "c"
refute_equal unique_string, "c"
refute_equal unique_string, 42
end
# Increasing is probably a terrible idea as well
def test_increasing
assert_equal increasing, 1
assert_equal increasing, 2
assert_equal increasing, 3
refute_equal increasing, 1
assert_equal increasing, 2
assert_equal increasing, 3
end
def test_any_time
assert_equal any_time, Time.now
refute_equal any_time, 42
end
def test_any_date
assert_equal any_date, Date.new
refute_equal any_date, 42
end
end
module Anything
class Anything
def initialize(*args)
@args = args
end
def ==(*)
true
end
def inspect
"#<%s>" % self.class.name.sub("Anything::", "")
end
def ^(other)
Composite.new(self, other)
end
end
def anything
Anything.new
end
class Composite < SimpleDelegator
def initialize(left, right)
super(left)
@right = right
end
def ==(o)
__getobj__.==(o) && @right.==(o)
end
def ^(other)
Composite.new(self, other)
end
def inspect
"#<Composite #{__getobj__.inspect} #{@right.inspect}>"
end
end
class AnyInteger < Anything
def ==(o)
o.is_a?(Integer)
end
end
def any_integer
AnyInteger.new
end
class AnyNumber < Anything
def ==(o)
o.is_a?(Numeric)
end
end
def any_number
AnyNumber.new
end
class EvenNumber < AnyNumber
def ==(o)
super && o.even?
end
end
def even_number
EvenNumber.new
end
class OddNumber < AnyNumber
def ==(o)
super && o.odd?
end
end
def odd_number
OddNumber.new
end
class AnyString < Anything
def ==(o)
o.is_a?(String)
end
def to_str
self
end
end
def any_string
AnyString.new
end
class StringOfLength < AnyString
def initialize(expected_length)
super
@expected_length = expected_length
end
def ==(o)
super && o.length == @expected_length
end
def inspect
"#<StringOfLength #@expected_length>"
end
end
def string_of_length(expected_length)
StringOfLength.new(expected_length)
end
class SortedArray < Anything
def ==(o)
o == o.sort
end
def to_ary
self
end
end
def sorted_array
SortedArray.new
end
class AnyUnique < Anything
def initialize
@seen = Set.new
end
def ==(o)
if @seen.include?(o)
false
else
@seen << o
true
end
end
end
def any_unique
@_any_unique ||= AnyUnique.new
end
class Increasing < Anything
def initialize
@last = nil
@for_inspect = nil
end
def ==(o)
@for_inspect = @last
if @last
result = o > @last
@last = o
result
else
@last = o
super
end
end
def inspect
"#<Increasing last=#{@for_inspect.inspect}>"
end
end
def increasing
@_increasing ||= Increasing.new
end
class UpcaseString < AnyString
def ==(o)
super && o.upcase == o
end
end
def upcase_string
UpcaseString.new
end
class AnyTime < Anything
def ==(o)
o.is_a?(Time)
end
end
def any_time
AnyTime.new
end
class AnyDate < Anything
def ==(o)
o.is_a?(Date)
end
end
def any_date
AnyDate.new
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment