mirror of
https://github.com/CatalaLang/catala.git
synced 2024-11-08 07:51:43 +03:00
Clerk report: add JUnit-compatible XML output
This commit is contained in:
parent
cdb31ffd57
commit
29cb1978e0
@ -177,6 +177,12 @@ module Cli = struct
|
|||||||
& pos_all string []
|
& pos_all string []
|
||||||
& info [] ~docv:"FILE(S)" ~doc:"File(s) or folder(s) to process")
|
& info [] ~docv:"FILE(S)" ~doc:"File(s) or folder(s) to process")
|
||||||
|
|
||||||
|
let files =
|
||||||
|
Arg.(
|
||||||
|
value
|
||||||
|
& pos_all file []
|
||||||
|
& info [] ~docv:"FILE(S)" ~doc:"File(s) to process")
|
||||||
|
|
||||||
let single_file =
|
let single_file =
|
||||||
Arg.(
|
Arg.(
|
||||||
required
|
required
|
||||||
@ -228,6 +234,14 @@ module Cli = struct
|
|||||||
~doc:"Display the full list of tests that have been run" );
|
~doc:"Display the full list of tests that have been run" );
|
||||||
])
|
])
|
||||||
|
|
||||||
|
let report_xml =
|
||||||
|
Arg.(
|
||||||
|
value
|
||||||
|
& flag
|
||||||
|
& info ["xml"]
|
||||||
|
~env:(Cmd.Env.info "CATALA_XML_REPORT")
|
||||||
|
~doc:"Output the test report in JUnit-compatible XML format")
|
||||||
|
|
||||||
let diff_command =
|
let diff_command =
|
||||||
Arg.(
|
Arg.(
|
||||||
value
|
value
|
||||||
@ -940,6 +954,7 @@ let test_cmd =
|
|||||||
(reset_test_outputs : bool)
|
(reset_test_outputs : bool)
|
||||||
(test_flags : string list)
|
(test_flags : string list)
|
||||||
verbosity
|
verbosity
|
||||||
|
xml
|
||||||
(diff_command : string option option)
|
(diff_command : string option option)
|
||||||
(ninja_flags : string list) =
|
(ninja_flags : string list) =
|
||||||
set_report_verbosity verbosity;
|
set_report_verbosity verbosity;
|
||||||
@ -959,6 +974,9 @@ let test_cmd =
|
|||||||
let reports = List.flatten (List.map read_many targets) in
|
let reports = List.flatten (List.map read_many targets) in
|
||||||
if reset_test_outputs then
|
if reset_test_outputs then
|
||||||
let () =
|
let () =
|
||||||
|
if xml then
|
||||||
|
Message.error
|
||||||
|
"Options @{<bold>--xml@} and @{<bold>--reset@} are incompatible";
|
||||||
let ppf = Message.formatter_of_out_channel stdout () in
|
let ppf = Message.formatter_of_out_channel stdout () in
|
||||||
match List.filter (fun f -> f.successful < f.total) reports with
|
match List.filter (fun f -> f.successful < f.total) reports with
|
||||||
| [] ->
|
| [] ->
|
||||||
@ -992,7 +1010,7 @@ let test_cmd =
|
|||||||
(List.length need_reset)
|
(List.length need_reset)
|
||||||
in
|
in
|
||||||
raise (Catala_utils.Cli.Exit_with 0)
|
raise (Catala_utils.Cli.Exit_with 0)
|
||||||
else if summary ~build_dir reports then
|
else if (if xml then print_xml else summary) ~build_dir reports then
|
||||||
raise (Catala_utils.Cli.Exit_with 0)
|
raise (Catala_utils.Cli.Exit_with 0)
|
||||||
else raise (Catala_utils.Cli.Exit_with 1)
|
else raise (Catala_utils.Cli.Exit_with 1)
|
||||||
| 1 -> raise (Catala_utils.Cli.Exit_with 10) (* Ninja build failed *)
|
| 1 -> raise (Catala_utils.Cli.Exit_with 10) (* Ninja build failed *)
|
||||||
@ -1013,6 +1031,7 @@ let test_cmd =
|
|||||||
$ Cli.reset_test_outputs
|
$ Cli.reset_test_outputs
|
||||||
$ Cli.test_flags
|
$ Cli.test_flags
|
||||||
$ Cli.report_verbosity
|
$ Cli.report_verbosity
|
||||||
|
$ Cli.report_xml
|
||||||
$ Cli.diff_command
|
$ Cli.diff_command
|
||||||
$ Cli.ninja_flags)
|
$ Cli.ninja_flags)
|
||||||
|
|
||||||
@ -1076,14 +1095,14 @@ let runtest_cmd =
|
|||||||
$ Cli.single_file)
|
$ Cli.single_file)
|
||||||
|
|
||||||
let report_cmd =
|
let report_cmd =
|
||||||
let run color debug verbosity diff_command build_dir file =
|
let run color debug verbosity xml diff_command build_dir files =
|
||||||
let _options = Catala_utils.Global.enforce_options ~debug ~color () in
|
let _options = Catala_utils.Global.enforce_options ~debug ~color () in
|
||||||
let build_dir = Option.value ~default:"_build" build_dir in
|
let build_dir = Option.value ~default:"_build" build_dir in
|
||||||
set_report_verbosity verbosity;
|
set_report_verbosity verbosity;
|
||||||
Clerk_report.set_display_flags ~diff_command ();
|
Clerk_report.set_display_flags ~diff_command ();
|
||||||
let open Clerk_report in
|
let open Clerk_report in
|
||||||
let tests = read_many file in
|
let tests = List.flatten (List.map read_many files) in
|
||||||
let success = summary ~build_dir tests in
|
let success = (if xml then print_xml else summary) ~build_dir tests in
|
||||||
exit (if success then 0 else 1)
|
exit (if success then 0 else 1)
|
||||||
in
|
in
|
||||||
let doc =
|
let doc =
|
||||||
@ -1096,9 +1115,10 @@ let report_cmd =
|
|||||||
$ Cli.Global.color
|
$ Cli.Global.color
|
||||||
$ Cli.Global.debug
|
$ Cli.Global.debug
|
||||||
$ Cli.report_verbosity
|
$ Cli.report_verbosity
|
||||||
|
$ Cli.report_xml
|
||||||
$ Cli.diff_command
|
$ Cli.diff_command
|
||||||
$ Cli.build_dir
|
$ Cli.build_dir
|
||||||
$ Cli.single_file)
|
$ Cli.files)
|
||||||
|
|
||||||
let main_cmd =
|
let main_cmd =
|
||||||
Cmd.group Cli.info [build_cmd; test_cmd; run_cmd; runtest_cmd; report_cmd]
|
Cmd.group Cli.info [build_cmd; test_cmd; run_cmd; runtest_cmd; report_cmd]
|
||||||
|
@ -183,38 +183,38 @@ let print_diff ppf p1 p2 =
|
|||||||
let catala_commands_with_output_flag =
|
let catala_commands_with_output_flag =
|
||||||
["makefile"; "html"; "latex"; "ocaml"; "python"; "r"; "c"]
|
["makefile"; "html"; "latex"; "ocaml"; "python"; "r"; "c"]
|
||||||
|
|
||||||
let display ~build_dir file ppf t =
|
let pfile ~build_dir f =
|
||||||
let pfile f =
|
|
||||||
f
|
f
|
||||||
|> String.remove_prefix ~prefix:(build_dir ^ Filename.dir_sep)
|
|> String.remove_prefix ~prefix:(build_dir ^ Filename.dir_sep)
|
||||||
|> String.remove_prefix ~prefix:(Sys.getcwd () ^ Filename.dir_sep)
|
|> String.remove_prefix ~prefix:(Sys.getcwd () ^ Filename.dir_sep)
|
||||||
in
|
|
||||||
let command_line_cleaned =
|
let clean_command_line ~build_dir file cl =
|
||||||
List.filter_map
|
cl
|
||||||
(fun s -> if s = "--directory=" ^ build_dir then None else Some (pfile s))
|
|> List.filter_map (fun s ->
|
||||||
t.command_line
|
if s = "--directory=" ^ build_dir then None
|
||||||
|
else Some (pfile ~build_dir s))
|
||||||
|> (function
|
|> (function
|
||||||
| catala :: cmd :: args ->
|
| catala :: cmd :: args ->
|
||||||
catala :: cmd :: "-I" :: Filename.dirname file :: args
|
catala :: cmd :: "-I" :: Filename.dirname file :: args
|
||||||
| cl -> cl)
|
| cl -> cl)
|
||||||
|> function
|
|> function
|
||||||
| catala :: cmd :: args
|
| catala :: cmd :: args
|
||||||
when List.mem
|
when List.mem (String.lowercase_ascii cmd) catala_commands_with_output_flag
|
||||||
(String.lowercase_ascii cmd)
|
->
|
||||||
catala_commands_with_output_flag ->
|
|
||||||
(catala :: cmd :: args) @ ["-o -"]
|
(catala :: cmd :: args) @ ["-o -"]
|
||||||
| cl -> cl
|
| cl -> cl
|
||||||
in
|
|
||||||
|
let display ~build_dir file ppf t =
|
||||||
let pp_pos ppf (start, stop) =
|
let pp_pos ppf (start, stop) =
|
||||||
assert (start.Lexing.pos_fname = stop.Lexing.pos_fname);
|
assert (start.Lexing.pos_fname = stop.Lexing.pos_fname);
|
||||||
Format.fprintf ppf "@{<cyan>%s:%d-%d@}"
|
Format.fprintf ppf "@{<cyan>%s:%d-%d@}"
|
||||||
(pfile start.Lexing.pos_fname)
|
(pfile ~build_dir start.Lexing.pos_fname)
|
||||||
start.Lexing.pos_lnum stop.Lexing.pos_lnum
|
start.Lexing.pos_lnum stop.Lexing.pos_lnum
|
||||||
in
|
in
|
||||||
let print_command () =
|
let print_command () =
|
||||||
Format.fprintf ppf "@,@[<h>$ @{<yellow>%a@}@]"
|
Format.fprintf ppf "@,@[<h>$ @{<yellow>%a@}@]"
|
||||||
(Format.pp_print_list ~pp_sep:Format.pp_print_space Format.pp_print_string)
|
(Format.pp_print_list ~pp_sep:Format.pp_print_space Format.pp_print_string)
|
||||||
command_line_cleaned
|
(clean_command_line ~build_dir file t.command_line)
|
||||||
in
|
in
|
||||||
Format.pp_open_vbox ppf 2;
|
Format.pp_open_vbox ppf 2;
|
||||||
if t.success then (
|
if t.success then (
|
||||||
@ -345,3 +345,46 @@ let summary ~build_dir tests =
|
|||||||
Format.pp_close_box ppf ();
|
Format.pp_close_box ppf ();
|
||||||
Format.pp_print_flush ppf ();
|
Format.pp_print_flush ppf ();
|
||||||
success = total
|
success = total
|
||||||
|
|
||||||
|
let print_xml ~build_dir tests =
|
||||||
|
let ffile ppf f = Format.pp_print_string ppf (pfile ~build_dir f) in
|
||||||
|
let ppf = Message.formatter_of_out_channel stdout () in
|
||||||
|
let tests = List.filter (fun f -> f.total > 0) tests in
|
||||||
|
let success, total =
|
||||||
|
List.fold_left
|
||||||
|
(fun (success, total) file ->
|
||||||
|
success + file.successful, total + file.total)
|
||||||
|
(0, 0) tests
|
||||||
|
in
|
||||||
|
Format.fprintf ppf "@[<v><?xml version=\"1.0\" encoding=\"UTF-8\"?>@,";
|
||||||
|
Format.fprintf ppf "@[<v 2><testsuites tests=\"%d\" failures=\"%d\">@,"
|
||||||
|
success (total - success);
|
||||||
|
Format.pp_print_list
|
||||||
|
(fun ppf f ->
|
||||||
|
Format.fprintf ppf
|
||||||
|
"@[<v 2>@[<hov 1><testsuite@ name=\"%a\"@ tests=\"%d\"@ \
|
||||||
|
failures=\"%d\">@]@,"
|
||||||
|
ffile f.name f.total (f.total - f.successful);
|
||||||
|
Format.pp_print_list
|
||||||
|
(fun ppf t ->
|
||||||
|
Format.fprintf ppf "@[<v 2><testcase line=\"%d\">"
|
||||||
|
(fst t.expected).Lexing.pos_lnum;
|
||||||
|
Format.fprintf ppf
|
||||||
|
"@,\
|
||||||
|
@[<hv 2><property name=\"description\">@,\
|
||||||
|
@[<hov 2>%a@]@;\
|
||||||
|
<0 -2></property>@]"
|
||||||
|
(Format.pp_print_list ~pp_sep:Format.pp_print_space
|
||||||
|
Format.pp_print_string)
|
||||||
|
(clean_command_line ~build_dir f.name t.command_line);
|
||||||
|
if not t.success then (
|
||||||
|
Format.fprintf ppf
|
||||||
|
"@,@[<v 2><failure message=\"Output differs from reference\">@,";
|
||||||
|
print_diff ppf t.expected t.result;
|
||||||
|
Format.fprintf ppf "@]@,</failure>");
|
||||||
|
Format.fprintf ppf "@]@,</testcase>")
|
||||||
|
ppf f.tests;
|
||||||
|
Format.fprintf ppf "@]@,</testsuite>")
|
||||||
|
ppf tests;
|
||||||
|
Format.fprintf ppf "@]@,</testsuites>@,@]@.";
|
||||||
|
success = total
|
||||||
|
@ -39,6 +39,10 @@ val display : build_dir:File.t -> File.t -> Format.formatter -> test -> unit
|
|||||||
val summary : build_dir:File.t -> file list -> bool
|
val summary : build_dir:File.t -> file list -> bool
|
||||||
(** Displays a summary to stdout; returns true if all tests succeeded *)
|
(** Displays a summary to stdout; returns true if all tests succeeded *)
|
||||||
|
|
||||||
|
val print_xml : build_dir:File.t -> file list -> bool
|
||||||
|
(** Displays a summary in JUnit XML comptible format to stdout; returns true if
|
||||||
|
all tests succeeded *)
|
||||||
|
|
||||||
val set_display_flags :
|
val set_display_flags :
|
||||||
?files:[ `All | `Failed | `None ] ->
|
?files:[ `All | `Failed | `None ] ->
|
||||||
?tests:[ `All | `FailedFile | `Failed | `None ] ->
|
?tests:[ `All | `FailedFile | `Failed | `None ] ->
|
||||||
|
Loading…
Reference in New Issue
Block a user