Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run all tests by default; ability to run tests by arbitrary path(s) #6

Merged
merged 1 commit into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions lib/mighty_test/cli.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module MightyTest
class CLI
def initialize(env: ENV, option_parser: OptionParser.new, runner: MinitestRunner.new)
def initialize(file_system: FileSystem.new, env: ENV, option_parser: OptionParser.new, runner: MinitestRunner.new)
@file_system = file_system
@env = env.to_h
@option_parser = option_parser
@runner = runner
Expand All @@ -26,7 +27,7 @@ def run(argv: ARGV)

private

attr_reader :env, :path_args, :extra_args, :options, :option_parser, :runner
attr_reader :file_system, :env, :path_args, :extra_args, :options, :option_parser, :runner

def print_help
# Minitest already prints the `-h, --help` option, so omit mighty_test's
Expand All @@ -44,14 +45,33 @@ def run_test_by_line_number
test_name = TestParser.new(path).test_name_at_line(line.to_i)

if test_name
runner.run_inline_and_exit!(path, args: ["-n", "/^#{Regexp.quote(test_name)}$/"] + extra_args)
run_tests_and_exit!(path, flags: ["-n", "/^#{Regexp.quote(test_name)}$/"])
else
runner.run_inline_and_exit!(args: extra_args)
run_tests_and_exit!
end
end

def run_tests_by_path
runner.run_inline_and_exit!(*path_args, args: extra_args)
test_paths = find_test_paths
run_tests_and_exit!(*test_paths)
end

def find_test_paths
return file_system.find_test_paths if path_args.empty?

path_args.flat_map do |path|
if Dir.exist?(path)
file_system.find_test_paths(path)
elsif File.exist?(path)
[path]
else
raise ArgumentError, "#{path} does not exist"
end
end
end

def run_tests_and_exit!(*test_paths, flags: [])
runner.run_inline_and_exit!(*test_paths, args: extra_args + flags)
end

def handle_exception(e) # rubocop:disable Naming/MethodParameterName
Expand Down
5 changes: 5 additions & 0 deletions lib/mighty_test/file_system.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,10 @@ def find_matching_test_file(path)
test_path = path[%r{^(?:app|lib)/(.+)\.[^\.]+$}, 1].then { "test/#{_1}_test.rb" }
test_path if test_path && File.exist?(test_path)
end

def find_test_paths(directory="test")
glob = File.join(directory, "**/*_test.rb")
Dir[glob]
end
end
end
3 changes: 2 additions & 1 deletion lib/mighty_test/option_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ def initialize
@parser = ::OptionParser.new do |op|
op.require_exact = true
op.banner = <<~BANNER
Usage: mt <test file>...
Usage: mt
mt [test file...] [test dir...]
mt --watch

BANNER
Expand Down
Empty file.
Empty file.
Empty file.
93 changes: 87 additions & 6 deletions test/mighty_test/cli_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

module MightyTest
class CLITest < Minitest::Test
include FixturesPath

def test_help_flag_prints_usage_and_minitest_options
result = cli_run(argv: ["--help"])

Expand All @@ -27,15 +29,96 @@ def test_version_flag_prints_version
assert_equal(VERSION, result.stdout.chomp)
end

def test_with_no_args_runs_all_tests_in_the_test_directory
with_fake_minitest_runner do |runner, executed_tests|
cli_run(argv: [], chdir: fixtures_path.join("rails_project"), runner:)

assert_equal(
%w[
test/helpers/users_helper_test.rb
test/models/account_test.rb
test/models/user_test.rb
test/system/users_system_test.rb
],
executed_tests.sort
)
end
end

def test_with_a_directory_arg_runs_all_test_files_in_that_directory
with_fake_minitest_runner do |runner, executed_tests|
cli_run(argv: ["test/models"], chdir: fixtures_path.join("rails_project"), runner:)

assert_equal(
%w[
test/models/account_test.rb
test/models/user_test.rb
],
executed_tests.sort
)
end
end

def test_with_a_mixture_of_file_and_directory_args_runs_all_matching_tests
with_fake_minitest_runner do |runner, executed_tests|
cli_run(argv: %w[test/system test/models/user_test.rb], chdir: fixtures_path.join("rails_project"), runner:)

assert_equal(
%w[
test/models/user_test.rb
test/system/users_system_test.rb
],
executed_tests.sort
)
end
end

def test_with_explict_file_args_runs_those_files_regardless_of_whether_they_appear_to_be_tests
with_fake_minitest_runner do |runner, executed_tests|
cli_run(argv: ["app/models/user.rb"], chdir: fixtures_path.join("rails_project"), runner:)

assert_equal(
%w[
app/models/user.rb
],
executed_tests.sort
)
end
end

def test_with_directory_args_only_runs_files_that_appear_to_be_tests
with_fake_minitest_runner do |runner, executed_tests|
cli_run(argv: ["app/models"], chdir: fixtures_path.join("rails_project"), runner:)

assert_empty(executed_tests)
end
end

def test_with_non_existent_path_raises_an_error
error = assert_raises(ArgumentError) do
cli_run(argv: ["test/models/non_existent_test.rb"], chdir: fixtures_path.join("rails_project"))
end

assert_includes(error.message, "test/models/non_existent_test.rb does not exist")
end

private

def cli_run(argv:, env: {}, stdin: nil, raise_on_failure: true)
def with_fake_minitest_runner
executed_tests = []
runner = MinitestRunner.new
runner.stub(:run_inline_and_exit!, ->(*test_files, **) { executed_tests.append(*test_files.flatten) }) do
yield(runner, executed_tests)
end
end

def cli_run(argv:, env: {}, chdir: ".", runner: nil, raise_on_failure: true)
exitstatus = true
orig_stdin = $stdin
$stdin = StringIO.new(stdin) if stdin

stdout, stderr = capture_io do
CLI.new(env:).run(argv:)
Dir.chdir(chdir) do
CLI.new(**{ env:, runner: }.compact).run(argv:)
end
rescue SystemExit => e
exitstatus = e.status
end
Expand All @@ -44,8 +127,6 @@ def cli_run(argv:, env: {}, stdin: nil, raise_on_failure: true)
raise "CLI exited with status: #{exitstatus}" if raise_on_failure && result.failure?

result
ensure
$stdin = orig_stdin
end
end
end