diff --git a/CHANGES.md b/CHANGES.md index 8dabaef6..91a52229 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -21,6 +21,10 @@ - Avoid exporting `list_tests` in the main test APIs (`Alcotest{,_lwt,_async}`). Use `Alcotest_engine` directly if you want this function. (#310, @CraigFe) +- Fix parsing of test filter ranges to allow '-' separators (e.g. `test alpha + 1-4`), as advertised in the manpage. The previously-used '..' separator is + also supported. (#312, @CraigFe) + ### 1.4.0 (2021-04-15) - Add `?here` and `?pos` arguments to the test assertion functions. These can be diff --git a/src/alcotest-engine/config.ml b/src/alcotest-engine/config.ml index 4195fc22..5856dfe1 100644 --- a/src/alcotest-engine/config.ml +++ b/src/alcotest-engine/config.ml @@ -148,7 +148,10 @@ module Key = struct if lower > upper then acc else range (succ lower) upper (lower :: acc) in let process_range acc s = - String.cuts ~sep:".." s |> List.map String.to_int |> function + String.cuts ~sep:".." s + |> List.concat_map (String.cuts ~sep:"-") + |> List.map String.to_int + |> function | [ Some i ] -> i :: acc | [ Some lower; Some upper ] when lower <= upper -> range lower upper acc @@ -172,7 +175,8 @@ module Key = struct and+ index_cases = let doc = "A comma-separated list of test case numbers (and ranges of numbers) \ - to run, e.g: '4,6-10,19'" + to run, e.g: '4,6-10,19'. When specifying ranges, both '-' and '..' \ + are accepted as valid separators." in Arg.( value diff --git a/src/alcotest-stdlib-ext/alcotest_stdlib_ext.ml b/src/alcotest-stdlib-ext/alcotest_stdlib_ext.ml index 89ca1168..6232b349 100644 --- a/src/alcotest-stdlib-ext/alcotest_stdlib_ext.ml +++ b/src/alcotest-stdlib-ext/alcotest_stdlib_ext.ml @@ -45,6 +45,15 @@ module List = struct in aux [] n l + let concat_map f l = + let rec aux f acc = function + | [] -> rev acc + | x :: l -> + let xs = f x in + (aux [@tailcall]) f (rev_append xs acc) l + in + aux f [] l + let filter_map f l = let rec inner acc = function | [] -> rev acc diff --git a/src/alcotest-stdlib-ext/alcotest_stdlib_ext.mli b/src/alcotest-stdlib-ext/alcotest_stdlib_ext.mli index b2e5ce35..bb39cb0f 100644 --- a/src/alcotest-stdlib-ext/alcotest_stdlib_ext.mli +++ b/src/alcotest-stdlib-ext/alcotest_stdlib_ext.mli @@ -27,6 +27,7 @@ module List : sig val rev_head : int -> 'a list -> 'a list (** Reverse a list, taking at most the first n elements of the original list. *) + val concat_map : ('a -> 'b list) -> 'a list -> 'b list val filter_map : ('a -> 'b option) -> 'a list -> 'b list val lift_result : ('a, 'b) result t -> ('a t, 'b t) result val init : int -> (int -> 'a) -> 'a list diff --git a/test/e2e/alcotest/passing/dune.inc b/test/e2e/alcotest/passing/dune.inc index 04a1b9f5..49dd1321 100644 --- a/test/e2e/alcotest/passing/dune.inc +++ b/test/e2e/alcotest/passing/dune.inc @@ -11,6 +11,7 @@ empty_test_name filter_name filter_name_regex + filter_range isatty json_output list_tests @@ -34,6 +35,7 @@ empty_test_name filter_name filter_name_regex + filter_range isatty json_output list_tests @@ -255,6 +257,25 @@ (action (diff filter_name_regex.expected filter_name_regex.processed))) +(rule + (target filter_range.actual) + (action + (with-outputs-to %{target} + (with-accepted-exit-codes (or 0 125) + (run %{dep:filter_range.exe} test main 0..1,1-3,5))))) + +(rule + (target filter_range.processed) + (action + (with-outputs-to %{target} + (run ../../strip_randomness.exe %{dep:filter_range.actual})))) + +(rule + (alias runtest) + (package alcotest) + (action + (diff filter_range.expected filter_range.processed))) + (rule (target isatty.actual) (action diff --git a/test/e2e/alcotest/passing/filter_range.expected b/test/e2e/alcotest/passing/filter_range.expected new file mode 100644 index 00000000..4a8ef81f --- /dev/null +++ b/test/e2e/alcotest/passing/filter_range.expected @@ -0,0 +1,12 @@ +Testing `test/e2e/alcotest/passing/filter_range.ml'. +This run has ID `'. + + [OK] main 0 test-0. + [OK] main 1 test-1. + [OK] main 2 test-2. + [OK] main 3 test-3. + [SKIP] main 4 test-4. + [OK] main 5 test-5. + +Full test results in `/_build/_tests/'. +Test Successful in s. 5 tests run. diff --git a/test/e2e/alcotest/passing/filter_range.ml b/test/e2e/alcotest/passing/filter_range.ml new file mode 100644 index 00000000..37cbacb6 --- /dev/null +++ b/test/e2e/alcotest/passing/filter_range.ml @@ -0,0 +1,13 @@ +open Alcotest_stdlib_ext + +let () = + let should_run i = + (* Corresponds to ranges specified in [filter_range.opts]. *) + List.mem i [ 0; 1; 2; 3; 5 ] + in + let tests = + List.init 6 (fun i -> + Alcotest.test_case (Printf.sprintf "test-%d" i) `Quick (fun () -> + if not (should_run i) then failwith "Test should have been skipped")) + in + Alcotest.run __FILE__ [ ("main", tests) ] diff --git a/test/e2e/alcotest/passing/filter_range.opts b/test/e2e/alcotest/passing/filter_range.opts new file mode 100644 index 00000000..6f7ff430 --- /dev/null +++ b/test/e2e/alcotest/passing/filter_range.opts @@ -0,0 +1 @@ +test main 0..1,1-3,5