83 lines
2.1 KiB
Ruby
Executable File
83 lines
2.1 KiB
Ruby
Executable File
#!/usr/bin/env ruby
|
|
# frozen_string_literal: true
|
|
|
|
# Repo-level test runner for the mixed minitest/pytest suites under plugins/.
|
|
#
|
|
# bin/test # run every plugin suite
|
|
# bin/test os-backlog # run one plugin's suites (repeatable)
|
|
#
|
|
# Per plugin it runs `ruby tests/all.rb` when present (minitest) and
|
|
# `pytest tests/` when any tests/*_test.py or tests/test_*.py exists.
|
|
# pytest runs once per plugin so same-named test files (hook_test.py in
|
|
# several plugins) never collide on module import.
|
|
# os-vault's tests/ is an eval harness (harness.sh), not a unit suite,
|
|
# and is intentionally not run here.
|
|
|
|
require "open3"
|
|
|
|
class PluginSuite
|
|
RUNNERS = {
|
|
minitest: ->(dir) { ["ruby", "tests/all.rb"] },
|
|
pytest: ->(dir) { ["pytest", "-q", "tests"] }
|
|
}.freeze
|
|
|
|
attr_reader :name
|
|
|
|
def initialize(dir)
|
|
@dir = dir
|
|
@name = File.basename(dir)
|
|
end
|
|
|
|
def kinds
|
|
kinds = []
|
|
kinds << :minitest if File.exist?(File.join(@dir, "tests", "all.rb"))
|
|
kinds << :pytest if pytest_files?
|
|
kinds
|
|
end
|
|
|
|
def run(kind)
|
|
command = RUNNERS.fetch(kind).call(@dir)
|
|
stdout, status = Open3.capture2e(*command, chdir: @dir)
|
|
[status.success?, stdout]
|
|
end
|
|
|
|
private
|
|
|
|
def pytest_files?
|
|
Dir.glob(File.join(@dir, "tests", "{test_*,*_test}.py")).any?
|
|
end
|
|
end
|
|
|
|
repo_root = File.expand_path("..", __dir__)
|
|
requested = ARGV
|
|
suites = Dir.glob(File.join(repo_root, "plugins", "*"))
|
|
.select { |d| File.directory?(d) }
|
|
.map { |d| PluginSuite.new(d) }
|
|
.select { |s| requested.empty? || requested.include?(s.name) }
|
|
.sort_by(&:name)
|
|
|
|
unknown = requested - suites.map(&:name)
|
|
abort "bin/test: no such plugin(s): #{unknown.join(", ")}" unless unknown.empty?
|
|
|
|
failures = []
|
|
ran = 0
|
|
suites.each do |suite|
|
|
suite.kinds.each do |kind|
|
|
ran += 1
|
|
ok, output = suite.run(kind)
|
|
puts "#{ok ? "PASS" : "FAIL"} #{suite.name} (#{kind})"
|
|
unless ok
|
|
failures << "#{suite.name} (#{kind})"
|
|
puts output.lines.map { |l| " #{l}" }.join
|
|
end
|
|
end
|
|
end
|
|
|
|
if ran.zero?
|
|
puts "bin/test: no test suites found"
|
|
elsif failures.empty?
|
|
puts "#{ran} suites passed"
|
|
else
|
|
abort "#{failures.size}/#{ran} suites failed: #{failures.join(", ")}"
|
|
end
|