Skip to content

Commit

Permalink
Switch to assert style and introduce a new test runner (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
joeldrapper authored Dec 17, 2024
1 parent 1b3e504 commit 4e6810e
Show file tree
Hide file tree
Showing 61 changed files with 564 additions and 1,579 deletions.
2 changes: 0 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ source "https://rubygems.org"
# Specify your gem's dependencies in quickdraw.gemspec
gemspec

gem "rspec-expectations"

if RUBY_ENGINE == "ruby"
group :development do
gem "rubocop"
Expand Down
10 changes: 0 additions & 10 deletions config/quickdraw.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
# frozen_string_literal: true

require_relative "../test/support/matchers/pass_fail"

module BazMatcher
def baz?
success!
end
end

Quickdraw.configure do |config|
config.matcher Matchers::PassFail, Proc
config.matcher BazMatcher, String
end

# require 'simplecov'
Expand Down
19 changes: 3 additions & 16 deletions lib/quickdraw.rb
Original file line number Diff line number Diff line change
@@ -1,36 +1,23 @@
# frozen_string_literal: true

require "concurrent/map"
require "concurrent/array"
require "concurrent/set"

module Quickdraw
autoload :ArgumentError, "quickdraw/errors/argument_error"
autoload :Assertions, "quickdraw/assertions"
autoload :CLI, "quickdraw/cli"
autoload :Cluster, "quickdraw/cluster"
autoload :ConcurrentArray, "quickdraw/concurrent_array"
autoload :ConcurrentInteger, "quickdraw/concurrent_integer"
autoload :Configuration, "quickdraw/configuration"
autoload :Context, "quickdraw/context"
autoload :Expectation, "quickdraw/expectation"
autoload :Map, "quickdraw/map"
autoload :Matchers, "quickdraw/matchers"
autoload :Minitest, "quickdraw/minitest"
autoload :Never, "quickdraw/never"
autoload :Pipe, "quickdraw/pipe"
autoload :Platform, "quickdraw/platform"
autoload :Queue, "quickdraw/queue"
autoload :Registry, "quickdraw/registry"
autoload :RSpec, "quickdraw/rspec"
autoload :Run, "quickdraw/run"
autoload :Runner, "quickdraw/runner"
autoload :Test, "quickdraw/test"
autoload :Timer, "quickdraw/timer"
autoload :Watcher, "quickdraw/watcher"
autoload :Worker, "quickdraw/worker"

Null = Object.new.freeze
Error = Module.new
Config = Configuration.new
MATCHERS = Concurrent::Map.new

def self.configure(&)
yield Config
Expand Down
123 changes: 123 additions & 0 deletions lib/quickdraw/assertions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# frozen_string_literal: true

module Quickdraw::Assertions
def assert_equal(a, b)
assert(a == b) do
"expected #{a} to == #{b}"
end
end

def refute_equal(a, b)
refute(a == b) do
"expected #{a} to not == #{b}"
end
end

def assert_empty(collection)
assert(collection.empty?) do
"expected #{collection.class} to be empty"
end
end

def assert_includes(collection, item)
assert(collection.include?(item)) do
"expected #{collection.inspect} to include #{item.inspect}"
end
end

def refute_includes(collection, item)
refute(collection.include?(item)) do
"expected #{collection.inspect} to not include #{item.inspect}"
end
end

def assert_instance_of(object, klass)
assert(object.instance_of?(klass)) do
"expected #{object.class} to be an instance of #{klass}"
end
end

def refute_instance_of(object, klass)
refute(object.instance_of?(klass)) do
"expected #{object.class} to not be an instance of #{klass}"
end
end

def assert_kind_of(object, klass)
assert(object.kind_of?(klass)) do
"expected #{object.class} to be a kind of #{klass}"
end
end

def assert_match(pattern, object)
assert(pattern =~ object) do
"expected #{object.inspect} to match #{pattern.inspect}"
end
end

def refute_match(pattern, object)
refute(pattern =~ object) do
"expected #{object.inspect} to not match #{pattern.inspect}"
end
end

def refute_kind_of(object, klass)
refute(object.kind_of?(klass)) do
"expected #{object.class} to not be a kind of #{klass}"
end
end

def refute_empty(collection)
refute(collection.empty?) do
"expected #{collection.class} to not be empty"
end
end

def assert_raises(error)
yield
failure! { "expected block to raise #{error.inspect} but nothing was raised" }
rescue Exception => e
assert(error === e) do
"expected block to raise #{error.inspect} but #{e.class.inspect} was raised instead"
end

e
end

def refute_raises
yield
success!
rescue Exception => e
failure! { "expected block not to raise, but #{e.class.inspect} was raised" }
end

def assert_operator(object, operator, other)
assert object.public_send(operator, other) do
"expected #{object.inspect} to #{operator} #{other.inspect}"
end
end

def refute_operator(object, operator, other)
refute object.public_send(operator, other) do
"expected #{object.inspect} to not #{operator} #{other.inspect}"
end
end

def assert_respond_to(object, method_name)
assert object.respond_to?(method_name) do
"expected #{object.inspect} to respond to ##{method_name}"
end
end

def assert_same(a, b)
assert a.equal?(b) do
"expected #{a.inspect} to be the same object as #{b.inspect}"
end
end

def refute_same(a, b)
refute a.equal?(b) do
"expected #{a.inspect} to not be the same object as #{b.inspect}"
end
end
end
31 changes: 10 additions & 21 deletions lib/quickdraw/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
class Quickdraw::CLI
CONFIG_PATH = File.expand_path("config/quickdraw.rb")

autoload :ArgumentParser, "quickdraw/cli/argument_parser"

def initialize(args)
@args = args
end
Expand Down Expand Up @@ -107,35 +105,26 @@ def run
end

def watch
Quickdraw::Watcher.watch("./**/*.rb") do |paths|
time = Quickdraw::Timer.time do
Process.wait(
Process.fork do
print "\e[H\e[2J"
require CONFIG_PATH if File.exist?(CONFIG_PATH)

Quickdraw::Run.new(
processes: @processes || Quickdraw::Config.processes,
threads: @threads || Quickdraw::Config.threads,
files: Dir.glob(@files),
seed: @seed || Random.new_seed,
).call
end,
)
end
require "io/watch"

puts "Total time: #{time}"
IO::Watch::Monitor.new(["."], latency: 0.1).run do |event|
Process.fork do
print "\e[H\e[2J"
run_once
end
end
end

def run_once
require CONFIG_PATH if File.exist?(CONFIG_PATH)

Quickdraw::Run.new(
$quickdraw_runner = Quickdraw::Runner.new(
processes: @processes || Quickdraw::Config.processes,
threads: @threads || Quickdraw::Config.threads,
files: Dir.glob(@files),
seed: @seed || Random.new_seed,
).call
)

$quickdraw_runner.call
end
end
12 changes: 1 addition & 11 deletions lib/quickdraw/cluster.rb
Original file line number Diff line number Diff line change
@@ -1,22 +1,12 @@
# frozen_string_literal: true

class Quickdraw::Cluster
def self.call(n = Quickdraw::Platform.cpu_cores, &)
spawn(n, &).wait
end

def self.spawn(n = Quickdraw::Platform.cpu_cores, &block)
new.tap do |cluster|
n.times { cluster.fork(&block) }
end
end

def initialize
@workers = []
end

def fork(&)
@workers << Quickdraw::Worker.fork(&)
Quickdraw::Worker.fork(&).tap { |it| @workers << it }
end

def terminate
Expand Down
32 changes: 32 additions & 0 deletions lib/quickdraw/concurrent_array.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

class Quickdraw::ConcurrentArray
def initialize
@array = []
@monitor = Monitor.new
end

def <<(value)
@monitor.synchronize { @array << value }
end

def each(&)
@monitor.synchronize { @array.each(&) }
end

def concat(other)
@monitor.synchronize { @array.concat(other) }
end

def size
@monitor.synchronize { @array.size }
end

def any?
@monitor.synchronize { @array.any? }
end

def to_a
@monitor.synchronize { @array.dup }
end
end
16 changes: 16 additions & 0 deletions lib/quickdraw/concurrent_integer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

class Quickdraw::ConcurrentInteger
def initialize(value = 0)
@value = value
@monitor = Monitor.new
end

def increment(n = 1)
@monitor.synchronize { @value += n }
end

def value
@monitor.synchronize { @value }
end
end
17 changes: 11 additions & 6 deletions lib/quickdraw/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,31 @@

class Quickdraw::Configuration
DEFAULT_PROCESSES = Quickdraw::Platform.supports_forking? ? Quickdraw::Platform.non_blocking_cores : 1
DEFAULT_THREADS = 8
DEFAULT_THREADS = 4

def initialize
@registry = Quickdraw::Registry.new
@failure_symbol = "\e[31m⨯\e[0m"
@success_symbol = "\e[32m∘\e[0m"
@processes = DEFAULT_PROCESSES
@threads = DEFAULT_THREADS
@success_emoji = %w[💃 🕺 🎉 🎊 💪 👏 🙌 🥳 🎈 🌈 🎯 🏆]
@before_forking_callbacks = []
@after_forking_callbacks = []
end

attr_reader :registry

attr_accessor :failure_symbol
attr_accessor :processes
attr_accessor :success_emoji
attr_accessor :success_symbol
attr_accessor :threads
attr_reader :before_forking_callbacks
attr_reader :after_forking_callbacks

def before_forking(&block)
@before_forking_callbacks << block
end

def matcher(matcher, *types)
@registry.register(matcher, *types)
def after_forking(&block)
@after_forking_callbacks << block
end
end
Loading

0 comments on commit 4e6810e

Please sign in to comment.