cc-os/bin/test

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