Last active
August 29, 2015 14:18
-
-
Save wojtekmach/3e349a5a62f9cb1aac12 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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