aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPeter Andersson <[email protected]>2011-09-05 19:51:59 +0200
committerPeter Andersson <[email protected]>2011-09-23 12:24:55 +0200
commite91ba727f534553a34c05ad54247a0485e2429ff (patch)
tree79759dfa3c1d4af4297975ecdcc8d40288a2d507 /lib
parent6668a91b365b8390d8eb369f7d6c6294711a1fef (diff)
downloadotp-e91ba727f534553a34c05ad54247a0485e2429ff.tar.gz
otp-e91ba727f534553a34c05ad54247a0485e2429ff.tar.bz2
otp-e91ba727f534553a34c05ad54247a0485e2429ff.zip
Implement support for running suites with test case groups through the debugger
OTP-9518
Diffstat (limited to 'lib')
-rw-r--r--lib/common_test/doc/src/run_test_chapter.xml5
-rw-r--r--lib/common_test/src/ct_framework.erl35
-rw-r--r--lib/common_test/src/ct_run.erl75
3 files changed, 81 insertions, 34 deletions
diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml
index e668568795..e944f215f6 100644
--- a/lib/common_test/doc/src/run_test_chapter.xml
+++ b/lib/common_test/doc/src/run_test_chapter.xml
@@ -322,8 +322,9 @@
are to be executed by Common Test, and those functions only. If
the step option <c>config</c> is specified, breakpoints will
also be initially set on the configuration functions in the suite, i.e.
- <c>init_per_suite/1</c>, <c>end_per_suite/1</c>, <c>init_per_testcase/2</c>
- and <c>end_per_testcase/2</c>.</p>
+ <c>init_per_suite/1</c>, <c>end_per_suite/1</c>,
+ <c>init_per_group/2</c>, <c>end_per_group/2</c>,
+ <c>init_per_testcase/2</c> and <c>end_per_testcase/2</c>.</p>
<p>Common Test enables the Debugger auto attach feature, which means
that for every new interpreted test case function that starts to execute,
a new trace window will automatically pop up. (This is because each test
diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl
index 29caa27d94..089d5be871 100644
--- a/lib/common_test/src/ct_framework.erl
+++ b/lib/common_test/src/ct_framework.erl
@@ -24,8 +24,8 @@
-module(ct_framework).
--export([init_tc/3, end_tc/3, end_tc/4, get_suite/2, report/2, warn/1]).
--export([error_notification/4]).
+-export([init_tc/3, end_tc/3, end_tc/4, get_suite/2, get_all_cases/1]).
+-export([report/2, warn/1, error_notification/4]).
-export([get_logopts/0, format_comment/1, overview_html_header/1]).
@@ -781,6 +781,37 @@ get_suite(Mod, Name) ->
%%%-----------------------------------------------------------------
+get_all_cases(Suite) ->
+ case get_suite(Suite, all) of
+ [{?MODULE,error_in_suite,[[{error,_}=Error]]}] ->
+ Error;
+ [{?MODULE,error_in_suite,[[Error]]}] ->
+ {error,Error};
+ Tests ->
+ Cases = get_all_cases1(Suite, Tests),
+ lists:reverse(
+ lists:foldl(fun(TC, TCs) ->
+ case lists:member(TC, TCs) of
+ true -> TCs;
+ false -> [TC | TCs]
+ end
+ end, [], Cases))
+ end.
+
+get_all_cases1(Suite, [{conf,_Props,_Init,GrTests,_End} | Tests]) ->
+ get_all_cases1(Suite, GrTests) ++ get_all_cases1(Suite, Tests);
+
+get_all_cases1(Suite, [Test | Tests]) when is_atom(Test) ->
+ [{Suite,Test} | get_all_cases1(Suite, Tests)];
+
+get_all_cases1(Suite, [Test | Tests]) ->
+ [Test | get_all_cases1(Suite, Tests)];
+
+get_all_cases1(_, []) ->
+ [].
+
+%%%-----------------------------------------------------------------
+
find_groups(Mod, Name, TCs, GroupDefs) ->
Found = find(Mod, Name, TCs, GroupDefs, [], GroupDefs, false),
trim(Found).
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index 4ff062c2fa..2dd6ba08aa 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -2148,7 +2148,14 @@ maybe_interpret1(Suite, Cases, StepOpts) when is_list(Cases) ->
maybe_interpret2(Suite, Cases, StepOpts) ->
set_break_on_config(Suite, StepOpts),
- [i:ib(Suite, Case, 1) || Case <- Cases],
+ [begin try i:ib(Suite, Case, 1) of
+ _ -> ok
+ catch
+ _:_Error ->
+ io:format(user, "Invalid breakpoint: ~w:~w/1~n",
+ [Suite,Case])
+ end
+ end || Case <- Cases, is_atom(Case)],
test_server_ctrl:multiply_timetraps(infinity),
WinOp = case lists:member(keep_inactive, ensure_atom(StepOpts)) of
true -> no_kill;
@@ -2161,10 +2168,18 @@ maybe_interpret2(Suite, Cases, StepOpts) ->
set_break_on_config(Suite, StepOpts) ->
case lists:member(config, ensure_atom(StepOpts)) of
true ->
- i:ib(Suite, init_per_suite, 1),
- i:ib(Suite, init_per_testcase, 2),
- i:ib(Suite, end_per_testcase, 2),
- i:ib(Suite, end_per_suite, 1);
+ SetBPIfExists = fun(F,A) ->
+ case erlang:function_exported(Suite, F, A) of
+ true -> i:ib(Suite, F, A);
+ false -> ok
+ end
+ end,
+ SetBPIfExists(init_per_suite, 1),
+ SetBPIfExists(init_per_group, 2),
+ SetBPIfExists(init_per_testcase, 2),
+ SetBPIfExists(end_per_testcase, 2),
+ SetBPIfExists(end_per_group, 2),
+ SetBPIfExists(end_per_suite, 1);
false ->
ok
end.
@@ -2463,32 +2478,32 @@ is_suite(ModOrFile) when is_list(ModOrFile) ->
end.
get_all_testcases(Suite) ->
- %%! this needs to be updated to handle testcase groups later!!
- case catch Suite:all() of
- {'EXIT',Why} ->
- {error,Why};
- {skip,_} ->
- [];
- Cases ->
- AllCases =
- lists:foldl(fun({sequence,SeqName}, All) ->
- case catch Suite:sequences() of
- {'EXIT',_} ->
- All;
- Seqs ->
- case proplists:get_value(SeqName, Seqs) of
- undefined ->
- All;
- SeqCases ->
- lists:reverse(SeqCases) ++ All
- end
- end;
- (Case,All) ->
- [Case|All]
- end, [], Cases),
- lists:reverse(AllCases)
+ try ct_framework:get_all_cases(Suite) of
+ {error,_Reason} = Error ->
+ Error;
+ SuiteCases ->
+ Cases = [C || {_S,C} <- SuiteCases],
+ Cases1 =
+ try Suite:sequences() of
+ [] ->
+ Cases;
+ Seqs ->
+ TCs1 = lists:flatten([TCs || {_,TCs} <- Seqs]),
+ lists:reverse(
+ lists:foldl(fun(TC, Acc) ->
+ case lists:member(TC, Acc) of
+ true -> Acc;
+ false -> [TC | Acc]
+ end
+ end, [], Cases ++ TCs1))
+ catch
+ _:_ ->
+ Cases
+ end
+ catch
+ _:Error ->
+ {error,Error}
end.
-
%% Internal tracing support. If {ct_trace,TraceSpec} is present, the
%% TraceSpec file will be consulted and dbg used to trace function