Skip to content

Commit

Permalink
fix: Allow tests and specs to interact with stdin (#232)
Browse files Browse the repository at this point in the history
  • Loading branch information
dazuma authored Oct 5, 2023
1 parent 4e3c953 commit ae27f33
Show file tree
Hide file tree
Showing 17 changed files with 114 additions and 51 deletions.
3 changes: 2 additions & 1 deletion toys-dev
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ dir=$(cd `dirname $0` && pwd)
export TOYS_DEV=true
export TOYS_LIB_PATH="$dir/toys/lib"
export TOYS_CORE_LIB_PATH="$dir/toys-core/lib"
exec ruby --disable=gems "$dir/toys/bin/toys" "$@"
export TOYS_BIN_PATH="$dir/toys/bin/toys"
exec ruby --disable=gems "$TOYS_BIN_PATH" "$@"
1 change: 1 addition & 0 deletions toys/.rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ inherit_from: "../.rubocop-common.yml"
AllCops:
Exclude:
- "test/rubocop-cases/**/*"
- "test/rspec-cases/**/*"
- "core-docs/**/*"
Layout/LineLength:
Exclude:
Expand Down
1 change: 1 addition & 0 deletions toys/lib/toys.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
# don't get clobbered in case someone sets up bundler later.
unless ::ENV.key?("TOYS_CORE_LIB_PATH")
path = ::File.expand_path("../../toys-core-#{::Toys::VERSION}/lib", __dir__)
path = ::File.expand_path("../../toys-core/lib", __dir__) unless path && ::File.directory?(path)
unless path && ::File.directory?(path)
require "rubygems"
dep = ::Gem::Dependency.new("toys-core", "= #{::Toys::VERSION}")
Expand Down
24 changes: 11 additions & 13 deletions toys/lib/toys/templates/minitest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -269,27 +269,25 @@ def bundler_settings
libs = Array(template.libs)
ruby_args << "-I#{libs.join(::File::PATH_SEPARATOR)}" unless libs.empty?
ruby_args << "-w" if warnings
ruby_args << "-"
ruby_args << "--seed" << seed if seed
vv = verbosity
vv += 1 if template.verbose
ruby_args << "--verbose" if vv.positive?
ruby_args << "--name" << name if name
ruby_args << "--exclude" << exclude if exclude

if tests.empty?
Array(template.files).each do |pattern|
tests.concat(::Dir.glob(pattern))
end
tests.uniq!
end
code = ["require 'minitest/autorun'"] + tests.map { |file| "load '#{file}'" }
ruby_args << "-e" << code.join("\n")

result = exec_ruby(ruby_args, in: :controller) do |controller|
controller.in.puts("require 'minitest/autorun'")
tests.each do |file|
controller.in.puts("load '#{file}'")
end
end
ruby_args << "--"
ruby_args << "--seed" << seed if seed
vv = verbosity
vv += 1 if template.verbose
ruby_args << "--verbose" if vv.positive?
ruby_args << "--name" << name if name
ruby_args << "--exclude" << exclude if exclude

result = exec_ruby(ruby_args)
if result.error?
logger.error("Minitest failed!")
exit(result.exit_code)
Expand Down
11 changes: 6 additions & 5 deletions toys/lib/toys/templates/rdoc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -322,11 +322,12 @@ def bundler_settings
args << "-T" << template.template if template.template
args << "-f" << template.generator if template.generator

exec_ruby([], in: :controller) do |controller|
controller.in.puts("gem 'rdoc', *#{gem_requirements.inspect}")
controller.in.puts("require 'rdoc'")
controller.in.puts("::RDoc::RDoc.new.document(#{(args + files).inspect})")
end
code = <<~CODE
gem 'rdoc', *#{gem_requirements.inspect}
require 'rdoc'
::RDoc::RDoc.new.document(#{(args + files).inspect})
CODE
exec_ruby(["-e", code])
end
end
end
Expand Down
16 changes: 10 additions & 6 deletions toys/lib/toys/templates/rspec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,15 @@ def bundler_settings
libs = Array(template.libs)
ruby_args << "-I#{libs.join(::File::PATH_SEPARATOR)}" unless libs.empty?
ruby_args << "-w" if warnings
ruby_args << "-"

code = <<~CODE
gem 'rspec', *#{gem_requirements.inspect}
require 'rspec/core'
::RSpec::Core::Runner.invoke
CODE
ruby_args << "-e" << code

ruby_args << "--"
ruby_args << "--options" << template.options if template.options
ruby_args << "--order" << order if order
ruby_args << "--format" << format if format
Expand All @@ -364,11 +372,7 @@ def bundler_settings
ruby_args << "--tag" << tag if tag
ruby_args.concat(files)

result = exec_ruby(ruby_args, in: :controller) do |controller|
controller.in.puts("gem 'rspec', *#{gem_requirements.inspect}")
controller.in.puts("require 'rspec/core'")
controller.in.puts("::RSpec::Core::Runner.invoke")
end
result = exec_ruby(ruby_args)
if result.error?
logger.error("RSpec failed!")
exit(result.exit_code)
Expand Down
11 changes: 6 additions & 5 deletions toys/lib/toys/templates/rubocop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,12 @@ def bundler_settings

::Dir.chdir(context_directory || ::Dir.getwd) do
logger.info "Running RuboCop..."
result = exec_ruby([], in: :controller) do |controller|
controller.in.puts("gem 'rubocop', *#{template.gem_version.inspect}")
controller.in.puts("require 'rubocop'")
controller.in.puts("exit(::RuboCop::CLI.new.run(#{template.options.inspect}))")
end
code = <<~CODE
gem 'rubocop', *#{template.gem_version.inspect}
require 'rubocop'
exit(::RuboCop::CLI.new.run(#{template.options.inspect}))
CODE
result = exec_ruby(["-e", code])
if result.error?
logger.error "RuboCop failed!"
exit(1) if template.fail_on_error
Expand Down
22 changes: 12 additions & 10 deletions toys/lib/toys/templates/yardoc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -503,21 +503,23 @@ def bundler_settings
end
run_options.concat(files)

result = exec_ruby([], in: :controller) do |controller|
controller.in.puts("gem 'yard', *#{gem_requirements.inspect}")
controller.in.puts("require 'yard'")
controller.in.puts("::YARD::CLI::Yardoc.run(*#{run_options.inspect})")
end
code = <<~CODE
gem 'yard', *#{gem_requirements.inspect}
require 'yard'
::YARD::CLI::Yardoc.run(*#{run_options.inspect})
CODE
result = exec_ruby(["-e", code])
if result.error?
puts("Yardoc encountered errors", :red, :bold) unless verbosity.negative?
exit(1)
end
unless stats_options.empty?
result = exec_ruby([], in: :controller, out: :capture) do |controller|
controller.in.puts("gem 'yard', *#{gem_requirements.inspect}")
controller.in.puts("require 'yard'")
controller.in.puts("::YARD::CLI::Stats.run(*#{stats_options.inspect})")
end
code = <<~CODE
gem 'yard', *#{gem_requirements.inspect}
require 'yard'
::YARD::CLI::Stats.run(*#{stats_options.inspect})
CODE
result = exec_ruby(["-e", code], out: :capture)
puts result.captured_out
if result.error?
puts("Yardoc encountered errors", :red, :bold) unless verbosity.negative?
Expand Down
5 changes: 5 additions & 0 deletions toys/test/minitest-cases/stream/.toys.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# frozen_string_literal: true

truncate_load_path!

expand :minitest, files: "foo.rb"
9 changes: 9 additions & 0 deletions toys/test/minitest-cases/stream/foo.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

require "minitest/autorun"

describe "foo" do
it "reads hello" do
assert_equal("hello\n", $stdin.read)
end
end
2 changes: 1 addition & 1 deletion toys/test/rspec-cases/lib1/spec_fixture.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

module SpecFixture
def self.foo
:foo
"foo"
end
end
2 changes: 1 addition & 1 deletion toys/test/rspec-cases/lib2/spec_fixture.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

module SpecFixture
def self.foo
:bar
"bar"
end
end
2 changes: 1 addition & 1 deletion toys/test/rspec-cases/spec/my_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

describe SpecFixture do
it "returns foo" do
expect(SpecFixture.foo).to eql(:foo)
expect(SpecFixture.foo).to eql("foo")
end
end
5 changes: 5 additions & 0 deletions toys/test/rspec-cases/stream/.toys.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# frozen_string_literal: true

truncate_load_path!

expand :rspec, pattern: "*_spec.rb"
7 changes: 7 additions & 0 deletions toys/test/rspec-cases/stream/my_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

describe "streams" do
it "returns foo" do
expect($stdin.read.strip).to eql("foo")
end
end
14 changes: 14 additions & 0 deletions toys/test/test_minitest.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require "helper"
require "toys/utils/exec"

describe "minitest template" do
let(:template_lookup) { Toys::ModuleLookup.new.add_path("toys/templates") }
Expand Down Expand Up @@ -128,6 +129,7 @@
let(:cli) { Toys::CLI.new(middleware_stack: [], template_lookup: template_lookup) }
let(:loader) { cli.loader }
let(:cases_dir) { File.join(__dir__, "minitest-cases") }
let(:exec_service) { Toys::Utils::Exec.new }

it "runs passing tests" do
dir = cases_dir
Expand Down Expand Up @@ -163,5 +165,17 @@
end
assert_match(/1 failure/, out)
end

it "supports input streams" do
dir = "#{cases_dir}/stream"
args = ["--disable=gems", Toys.executable_path, "test"]
result = exec_service.exec_ruby(args, chdir: dir,
in: :controller, out: :capture) do |controller|
controller.in.puts "hello"
end
assert(result.success?)
assert_match(/0 failures/, result.captured_out)
assert_match(/0 errors/, result.captured_out)
end
end
end
30 changes: 22 additions & 8 deletions toys/test/test_rspec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require "helper"
require "toys/utils/exec"

describe "rspec template" do
let(:template_lookup) { Toys::ModuleLookup.new.add_path("toys/templates") }
Expand Down Expand Up @@ -155,12 +156,14 @@
describe "integration functionality" do
let(:cli) { Toys::CLI.new(middleware_stack: [], template_lookup: template_lookup) }
let(:loader) { cli.loader }
let(:cases_dir) { File.join(__dir__, "rspec-cases") }
let(:exec_service) { Toys::Utils::Exec.new }

it "executes a successful spec" do
cases_dir = File.join(__dir__, "rspec-cases")
dir = cases_dir
loader.add_block do
expand :rspec, libs: File.join(cases_dir, "lib1"),
pattern: File.join(cases_dir, "spec", "*_spec.rb")
set_context_directory dir
expand :rspec, libs: "lib1", pattern: "spec/*_spec.rb"
end
out, _err = capture_subprocess_io do
assert_equal(0, cli.run("spec"))
Expand All @@ -169,10 +172,10 @@
end

it "executes an unsuccessful spec" do
cases_dir = File.join(__dir__, "rspec-cases")
dir = cases_dir
loader.add_block do
expand :rspec, libs: File.join(cases_dir, "lib2"),
pattern: File.join(cases_dir, "spec", "*_spec.rb")
set_context_directory dir
expand :rspec, libs: "lib2", pattern: "spec/*_spec.rb"
end
out, _err = capture_subprocess_io do
refute_equal(0, cli.run("spec"))
Expand All @@ -181,14 +184,25 @@
end

it "honors the context_directory setting" do
cases_dir = File.join(__dir__, "rspec-cases")
dir = cases_dir
loader.add_block do
expand :rspec, libs: "lib1", pattern: "spec/*_spec.rb", context_directory: cases_dir
expand :rspec, libs: "lib1", pattern: "spec/*_spec.rb", context_directory: dir
end
out, _err = capture_subprocess_io do
assert_equal(0, cli.run("spec"))
end
assert_match(/1 example, 0 failures/, out)
end

it "supports input streams" do
dir = "#{cases_dir}/stream"
args = ["--disable=gems", Toys.executable_path, "spec"]
result = exec_service.exec_ruby(args, chdir: dir,
in: :controller, out: :capture) do |controller|
controller.in.puts "foo"
end
assert(result.success?)
assert_match(/0 failures/, result.captured_out)
end
end
end

0 comments on commit ae27f33

Please sign in to comment.