Refactor std::test
Separate the console output from the running of tests
This commit is contained in:
188
src/lib/test.rs
188
src/lib/test.rs
@@ -99,28 +99,128 @@ fn run_tests_console(opts: &test_opts, tests: &test_desc[]) -> bool {
|
|||||||
fn run_tests_console_(opts: &test_opts, tests: &test_desc[],
|
fn run_tests_console_(opts: &test_opts, tests: &test_desc[],
|
||||||
to_task: &test_to_task) -> bool {
|
to_task: &test_to_task) -> bool {
|
||||||
|
|
||||||
|
type test_state = @{
|
||||||
|
out: io::writer,
|
||||||
|
use_color: bool,
|
||||||
|
mutable total: uint,
|
||||||
|
mutable passed: uint,
|
||||||
|
mutable failed: uint,
|
||||||
|
mutable ignored: uint,
|
||||||
|
mutable failures: test_desc[]
|
||||||
|
};
|
||||||
|
|
||||||
|
fn callback(event: testevent, st: test_state) {
|
||||||
|
alt event {
|
||||||
|
te_filtered(filtered_tests) {
|
||||||
|
st.total = ivec::len(filtered_tests);
|
||||||
|
st.out.write_line(#fmt("\nrunning %u tests", st.total));
|
||||||
|
}
|
||||||
|
te_result(test, result) {
|
||||||
|
st.out.write_str(#fmt("test %s ... ", test.name));
|
||||||
|
alt result {
|
||||||
|
tr_ok. {
|
||||||
|
st.passed += 1u;
|
||||||
|
write_ok(st.out, st.use_color);
|
||||||
|
st.out.write_line("");
|
||||||
|
}
|
||||||
|
tr_failed. {
|
||||||
|
st.failed += 1u;
|
||||||
|
write_failed(st.out, st.use_color);
|
||||||
|
st.out.write_line("");
|
||||||
|
st.failures += ~[test];
|
||||||
|
}
|
||||||
|
tr_ignored. {
|
||||||
|
st.ignored += 1u;
|
||||||
|
write_ignored(st.out, st.use_color);
|
||||||
|
st.out.write_line("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let st = @{
|
||||||
|
out: io::stdout(),
|
||||||
|
use_color: use_color(),
|
||||||
|
mutable total: 0u,
|
||||||
|
mutable passed: 0u,
|
||||||
|
mutable failed: 0u,
|
||||||
|
mutable ignored: 0u,
|
||||||
|
mutable failures: ~[]
|
||||||
|
};
|
||||||
|
|
||||||
|
run_tests(opts, tests, to_task,
|
||||||
|
bind callback(_, st));
|
||||||
|
|
||||||
|
assert st.passed + st.failed + st.ignored == st.total;
|
||||||
|
let success = st.failed == 0u;
|
||||||
|
|
||||||
|
if !success {
|
||||||
|
st.out.write_line("\nfailures:");
|
||||||
|
for test: test_desc in st.failures {
|
||||||
|
let testname = test.name; // Satisfy alias analysis
|
||||||
|
st.out.write_line(#fmt(" %s", testname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
st.out.write_str(#fmt("\nresult: "));
|
||||||
|
if success {
|
||||||
|
write_ok(st.out, st.use_color);
|
||||||
|
} else { write_failed(st.out, st.use_color); }
|
||||||
|
st.out.write_str(#fmt(". %u passed; %u failed; %u ignored\n\n",
|
||||||
|
st.passed, st.failed, st.ignored));
|
||||||
|
|
||||||
|
ret success;
|
||||||
|
|
||||||
|
fn write_ok(out: &io::writer, use_color: bool) {
|
||||||
|
write_pretty(out, "ok", term::color_green, use_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_failed(out: &io::writer, use_color: bool) {
|
||||||
|
write_pretty(out, "FAILED", term::color_red, use_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_ignored(out: &io::writer, use_color: bool) {
|
||||||
|
write_pretty(out, "ignored", term::color_yellow, use_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_pretty(out: &io::writer, word: &str, color: u8,
|
||||||
|
use_color: bool) {
|
||||||
|
if use_color && term::color_supported() {
|
||||||
|
term::fg(out.get_buf_writer(), color);
|
||||||
|
}
|
||||||
|
out.write_str(word);
|
||||||
|
if use_color && term::color_supported() {
|
||||||
|
term::reset(out.get_buf_writer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_color() -> bool {
|
||||||
|
ret get_concurrency() == 1u;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag testevent {
|
||||||
|
te_filtered(test_desc[]);
|
||||||
|
te_result(test_desc, test_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_tests(opts: &test_opts, tests: &test_desc[],
|
||||||
|
to_task: &test_to_task, callback: fn(testevent)) {
|
||||||
|
|
||||||
let filtered_tests = filter_tests(opts, tests);
|
let filtered_tests = filter_tests(opts, tests);
|
||||||
|
|
||||||
let out = io::stdout();
|
callback(te_filtered(filtered_tests));
|
||||||
|
|
||||||
let total = ivec::len(filtered_tests);
|
|
||||||
out.write_line(#fmt("\nrunning %u tests", total));
|
|
||||||
|
|
||||||
let futures = ~[];
|
|
||||||
|
|
||||||
let passed = 0u;
|
|
||||||
let failed = 0u;
|
|
||||||
let ignored = 0u;
|
|
||||||
|
|
||||||
let failures = ~[];
|
|
||||||
|
|
||||||
// It's tempting to just spawn all the tests at once but that doesn't
|
// It's tempting to just spawn all the tests at once but that doesn't
|
||||||
// provide a great user experience because you might sit waiting for the
|
// provide a great user experience because you might sit waiting for the
|
||||||
// result of a particular test for an unusually long amount of time.
|
// result of a particular test for an unusually long amount of time.
|
||||||
let concurrency = get_concurrency();
|
let concurrency = get_concurrency();
|
||||||
log #fmt("using %u test tasks", concurrency);
|
log #fmt("using %u test tasks", concurrency);
|
||||||
|
let total = ivec::len(filtered_tests);
|
||||||
let run_idx = 0u;
|
let run_idx = 0u;
|
||||||
let wait_idx = 0u;
|
let wait_idx = 0u;
|
||||||
|
let futures = ~[];
|
||||||
|
|
||||||
while wait_idx < total {
|
while wait_idx < total {
|
||||||
while ivec::len(futures) < concurrency && run_idx < total {
|
while ivec::len(futures) < concurrency && run_idx < total {
|
||||||
@@ -129,73 +229,11 @@ fn run_tests_console_(opts: &test_opts, tests: &test_desc[],
|
|||||||
}
|
}
|
||||||
|
|
||||||
let future = futures.(0);
|
let future = futures.(0);
|
||||||
out.write_str(#fmt("running %s ... ", future.test.name));
|
|
||||||
let result = future.wait();
|
let result = future.wait();
|
||||||
alt result {
|
callback(te_result(future.test, result));
|
||||||
tr_ok. {
|
|
||||||
passed += 1u;
|
|
||||||
write_ok(out, concurrency);
|
|
||||||
out.write_line("");
|
|
||||||
}
|
|
||||||
tr_failed. {
|
|
||||||
failed += 1u;
|
|
||||||
write_failed(out, concurrency);
|
|
||||||
out.write_line("");
|
|
||||||
failures += ~[future.test];
|
|
||||||
}
|
|
||||||
tr_ignored. {
|
|
||||||
ignored += 1u;
|
|
||||||
write_ignored(out, concurrency);
|
|
||||||
out.write_line("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
futures = ivec::slice(futures, 1u, ivec::len(futures));
|
futures = ivec::slice(futures, 1u, ivec::len(futures));
|
||||||
wait_idx += 1u;
|
wait_idx += 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert (passed + failed + ignored == total);
|
|
||||||
let success = failed == 0u;
|
|
||||||
|
|
||||||
if !success {
|
|
||||||
out.write_line("\nfailures:");
|
|
||||||
for test: test_desc in failures {
|
|
||||||
out.write_line(#fmt(" %s", test.name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out.write_str(#fmt("\nresult: "));
|
|
||||||
if success {
|
|
||||||
write_ok(out, concurrency);
|
|
||||||
} else { write_failed(out, concurrency); }
|
|
||||||
out.write_str(#fmt(". %u passed; %u failed; %u ignored\n\n", passed,
|
|
||||||
failed, ignored));
|
|
||||||
|
|
||||||
ret success;
|
|
||||||
|
|
||||||
fn write_ok(out: &io::writer, concurrency: uint) {
|
|
||||||
write_pretty(out, "ok", term::color_green, concurrency);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_failed(out: &io::writer, concurrency: uint) {
|
|
||||||
write_pretty(out, "FAILED", term::color_red, concurrency);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_ignored(out: &io::writer, concurrency: uint) {
|
|
||||||
write_pretty(out, "ignored", term::color_yellow, concurrency);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_pretty(out: &io::writer, word: &str, color: u8,
|
|
||||||
concurrency: uint) {
|
|
||||||
// In the presence of concurrency, outputing control characters
|
|
||||||
// can cause some crazy artifacting
|
|
||||||
if concurrency == 1u && term::color_supported() {
|
|
||||||
term::fg(out.get_buf_writer(), color);
|
|
||||||
}
|
|
||||||
out.write_str(word);
|
|
||||||
if concurrency == 1u && term::color_supported() {
|
|
||||||
term::reset(out.get_buf_writer());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_concurrency() -> uint {
|
fn get_concurrency() -> uint {
|
||||||
|
|||||||
Reference in New Issue
Block a user