<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html xmlns:fn="http://www.w3.org/2005/02/xpath-functions"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link rel="stylesheet" href="../../../../doc/otp_doc.css" type="text/css"> <title>Erlang -- Event Handling</title> </head> <body bgcolor="white" text="#000000" link="#0000ff" vlink="#ff00ff" alink="#ff0000"><div id="container"> <script id="js" type="text/javascript" language="JavaScript" src="../../../../doc/js/flipmenu/flipmenu.js"></script><script id="js2" type="text/javascript" src="../../../../doc/js/erlresolvelinks.js"></script><script language="JavaScript" type="text/javascript"> <!-- function getWinHeight() { var myHeight = 0; if( typeof( window.innerHeight ) == 'number' ) { //Non-IE myHeight = window.innerHeight; } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { //IE 6+ in 'standards compliant mode' myHeight = document.documentElement.clientHeight; } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { //IE 4 compatible myHeight = document.body.clientHeight; } return myHeight; } function setscrollpos() { var objf=document.getElementById('loadscrollpos'); document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2; } function addEvent(obj, evType, fn){ if (obj.addEventListener){ obj.addEventListener(evType, fn, true); return true; } else if (obj.attachEvent){ var r = obj.attachEvent("on"+evType, fn); return r; } else { return false; } } addEvent(window, 'load', setscrollpos); //--></script><div id="leftnav"><div class="innertube"> <img alt="Erlang logo" src="../../../../doc/erlang-logo.png"><br><small><a href="users_guide.html">User's Guide</a><br><a href="index.html">Reference Manual</a><br><a href="release_notes.html">Release Notes</a><br><a href="../pdf/common_test-1.6.3.pdf">PDF</a><br><a href="../../../../doc/index.html">Top</a></small><p><strong>Common Test</strong><br><strong>User's Guide</strong><br><small>Version 1.6.3</small></p> <br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Chapters</strong></small></p> <ul class="flipMenu" imagepath="../../../../doc/js/flipmenu"> <li id="no" title="Common Test Basics" expanded="false">Common Test Basics<ul> <li><a href="basics_chapter.html"> Top of chapter </a></li> <li title="Introduction"><a href="basics_chapter.html#id66143">Introduction</a></li> <li title="Test Suite Organisation"><a href="basics_chapter.html#id61412">Test Suite Organisation</a></li> <li title="Support Libraries"><a href="basics_chapter.html#id67203">Support Libraries</a></li> <li title="Suites and Test Cases"><a href="basics_chapter.html#id61632">Suites and Test Cases</a></li> <li title="External Interfaces"><a href="basics_chapter.html#id63930">External Interfaces</a></li> </ul> </li> <li id="no" title="Getting Started" expanded="false">Getting Started<ul> <li><a href="getting_started_chapter.html"> Top of chapter </a></li> <li title="Are you new around here?"><a href="getting_started_chapter.html#id61356">Are you new around here?</a></li> <li title="Test case execution"><a href="getting_started_chapter.html#id63050">Test case execution</a></li> <li title="A simple test suite"><a href="getting_started_chapter.html#id63909">A simple test suite</a></li> <li title="A test suite with configuration functions"><a href="getting_started_chapter.html#id68094">A test suite with configuration functions</a></li> <li title="What happens next?"><a href="getting_started_chapter.html#id62545">What happens next?</a></li> </ul> </li> <li id="no" title="Installation" expanded="false">Installation<ul> <li><a href="install_chapter.html"> Top of chapter </a></li> <li title="General information"><a href="install_chapter.html#id66699">General information</a></li> </ul> </li> <li id="no" title="Writing Test Suites" expanded="false">Writing Test Suites<ul> <li><a href="write_test_chapter.html"> Top of chapter </a></li> <li title="Support for test suite authors"><a href="write_test_chapter.html#id71900">Support for test suite authors</a></li> <li title="Test suites"><a href="write_test_chapter.html#id70761">Test suites</a></li> <li title="Init and end per suite"><a href="write_test_chapter.html#id70806">Init and end per suite</a></li> <li title="Init and end per test case"><a href="write_test_chapter.html#id70917">Init and end per test case</a></li> <li title="Test cases"><a href="write_test_chapter.html#id71162">Test cases</a></li> <li title="Test case info function"><a href="write_test_chapter.html#id71322">Test case info function</a></li> <li title="Test suite info function"><a href="write_test_chapter.html#id71521">Test suite info function</a></li> <li title="Test case groups"><a href="write_test_chapter.html#id71611">Test case groups</a></li> <li title="The parallel property and nested groups"><a href="write_test_chapter.html#id72823">The parallel property and nested groups</a></li> <li title="Parallel test cases and IO"><a href="write_test_chapter.html#id72860">Parallel test cases and IO</a></li> <li title="Repeated groups"><a href="write_test_chapter.html#id72908">Repeated groups</a></li> <li title="Shuffled test case order"><a href="write_test_chapter.html#id73046">Shuffled test case order</a></li> <li title="Group info function"><a href="write_test_chapter.html#id73105">Group info function</a></li> <li title="Info functions for init- and end-configuration"><a href="write_test_chapter.html#id73139">Info functions for init- and end-configuration</a></li> <li title="Data and Private Directories"><a href="write_test_chapter.html#id73202">Data and Private Directories</a></li> <li title="Execution environment"><a href="write_test_chapter.html#id73327">Execution environment</a></li> <li title="Timetrap timeouts"><a href="write_test_chapter.html#id73364">Timetrap timeouts</a></li> <li title="Logging - categories and verbosity levels"><a href="write_test_chapter.html#id73549">Logging - categories and verbosity levels</a></li> <li title="Illegal dependencies"><a href="write_test_chapter.html#id73756">Illegal dependencies</a></li> </ul> </li> <li id="no" title="Test Structure" expanded="false">Test Structure<ul> <li><a href="test_structure_chapter.html"> Top of chapter </a></li> <li title="Test structure"><a href="test_structure_chapter.html#id73930">Test structure</a></li> <li title="Skipping test cases"><a href="test_structure_chapter.html#id73944">Skipping test cases</a></li> <li title="Definition of terms"><a href="test_structure_chapter.html#id74020">Definition of terms</a></li> </ul> </li> <li id="no" title="Examples and Templates" expanded="false">Examples and Templates<ul> <li><a href="example_chapter.html"> Top of chapter </a></li> <li title="Test suite example"><a href="example_chapter.html#id74246">Test suite example</a></li> <li title="Test suite templates"><a href="example_chapter.html#id74298">Test suite templates</a></li> </ul> </li> <li id="no" title="Running Tests" expanded="false">Running Tests<ul> <li><a href="run_test_chapter.html"> Top of chapter </a></li> <li title="Using the Common Test Framework"><a href="run_test_chapter.html#id74488">Using the Common Test Framework</a></li> <li title="Automatic compilation of test suites and help modules"><a href="run_test_chapter.html#id74528">Automatic compilation of test suites and help modules</a></li> <li title="Running tests from the OS command line"><a href="run_test_chapter.html#id74645">Running tests from the OS command line</a></li> <li title="Running tests from the Erlang shell or from an Erlang program"><a href="run_test_chapter.html#id75142">Running tests from the Erlang shell or from an Erlang program</a></li> <li title="Test case group execution"><a href="run_test_chapter.html#id75304">Test case group execution</a></li> <li title="Running the interactive shell mode"><a href="run_test_chapter.html#id75821">Running the interactive shell mode</a></li> <li title="Step by step execution of test cases with the Erlang Debugger"><a href="run_test_chapter.html#id76003">Step by step execution of test cases with the Erlang Debugger</a></li> <li title="Test Specifications"><a href="run_test_chapter.html#id76102">Test Specifications</a></li> <li title="Running tests from the Web based GUI"><a href="run_test_chapter.html#id76643">Running tests from the Web based GUI</a></li> <li title="Log files"><a href="run_test_chapter.html#id76735">Log files</a></li> <li title="HTML Style Sheets"><a href="run_test_chapter.html#id77053">HTML Style Sheets</a></li> <li title="Repeating tests"><a href="run_test_chapter.html#id77201">Repeating tests</a></li> <li title="Silent Connections"><a href="run_test_chapter.html#id77412">Silent Connections</a></li> </ul> </li> <li id="no" title="External Configuration Data" expanded="false">External Configuration Data<ul> <li><a href="config_file_chapter.html"> Top of chapter </a></li> <li title="General"><a href="config_file_chapter.html#id77631">General</a></li> <li title="Syntax"><a href="config_file_chapter.html#id77671">Syntax</a></li> <li title="Requiring and reading configuration data"><a href="config_file_chapter.html#id77695">Requiring and reading configuration data</a></li> <li title="Using configuration variables defined in multiple files"><a href="config_file_chapter.html#id77839">Using configuration variables defined in multiple files</a></li> <li title="Encrypted configuration files"><a href="config_file_chapter.html#id77870">Encrypted configuration files</a></li> <li title="Opening connections by using configuration data"><a href="config_file_chapter.html#id77934">Opening connections by using configuration data</a></li> <li title="User specific configuration data formats"><a href="config_file_chapter.html#id78002">User specific configuration data formats</a></li> <li title="Examples of configuration data handling"><a href="config_file_chapter.html#id78216">Examples of configuration data handling</a></li> <li title="Example of user specific configuration handler"><a href="config_file_chapter.html#id78268">Example of user specific configuration handler</a></li> </ul> </li> <li id="no" title="Code Coverage Analysis" expanded="false">Code Coverage Analysis<ul> <li><a href="cover_chapter.html"> Top of chapter </a></li> <li title="General"><a href="cover_chapter.html#id78384">General</a></li> <li title="Usage"><a href="cover_chapter.html#id78404">Usage</a></li> <li title="The cover specification file"><a href="cover_chapter.html#id78510">The cover specification file</a></li> <li title="Logging"><a href="cover_chapter.html#id78563">Logging</a></li> </ul> </li> <li id="no" title="Using Common Test for Large Scale Testing" expanded="false">Using Common Test for Large Scale Testing<ul> <li><a href="ct_master_chapter.html"> Top of chapter </a></li> <li title="General"><a href="ct_master_chapter.html#id78634">General</a></li> <li title="Usage"><a href="ct_master_chapter.html#id78668">Usage</a></li> <li title="Test Specifications"><a href="ct_master_chapter.html#id78815">Test Specifications</a></li> <li title="Automatic startup of test target nodes"><a href="ct_master_chapter.html#id78987">Automatic startup of test target nodes</a></li> </ul> </li> <li id="loadscrollpos" title="Event Handling" expanded="true">Event Handling<ul> <li><a href="event_handler_chapter.html"> Top of chapter </a></li> <li title="General"><a href="event_handler_chapter.html#id79190">General</a></li> <li title="Usage"><a href="event_handler_chapter.html#id79226">Usage</a></li> </ul> </li> <li id="no" title="Dependencies between Test Cases and Suites" expanded="false">Dependencies between Test Cases and Suites<ul> <li><a href="dependencies_chapter.html"> Top of chapter </a></li> <li title="General"><a href="dependencies_chapter.html#id80143">General</a></li> <li title="Saving configuration data"><a href="dependencies_chapter.html#id80265">Saving configuration data</a></li> <li title="Sequences"><a href="dependencies_chapter.html#id80430">Sequences</a></li> </ul> </li> <li id="no" title="Common Test Hooks" expanded="false">Common Test Hooks<ul> <li><a href="ct_hooks_chapter.html"> Top of chapter </a></li> <li title="General"><a href="ct_hooks_chapter.html#id80622">General</a></li> <li title="Installing a CTH"><a href="ct_hooks_chapter.html#id80676">Installing a CTH</a></li> <li title="CTH Scope"><a href="ct_hooks_chapter.html#id80835">CTH Scope</a></li> <li title="Manipulating tests"><a href="ct_hooks_chapter.html#id81189">Manipulating tests</a></li> <li title="Example CTH"><a href="ct_hooks_chapter.html#id81482">Example CTH</a></li> <li title="Built-in CTHs"><a href="ct_hooks_chapter.html#id81535">Built-in CTHs</a></li> </ul> </li> <li id="no" title="Some thoughts about testing" expanded="false">Some thoughts about testing<ul> <li><a href="why_test_chapter.html"> Top of chapter </a></li> <li title="Goals"><a href="why_test_chapter.html#id81722">Goals</a></li> <li title="What to test?"><a href="why_test_chapter.html#id81742">What to test?</a></li> </ul> </li> </ul> </div></div> <div id="content"> <div class="innertube"> <h1>11 Event Handling</h1> <h3><a name="id79190">11.1 General</a></h3> <a name="event_handling"></a> <p>It is possible for the operator of a Common Test system to receive event notifications continously during a test run. It is reported e.g. when a test case starts and stops, what the current count of successful, failed and skipped cases is, etc. This information can be used for different purposes such as logging progress and results on other format than HTML, saving statistics to a database for report generation and test system supervision.</p> <p>Common Test has a framework for event handling which is based on the OTP event manager concept and gen_event behaviour. When the Common Test server starts, it spawns an event manager. During test execution the manager gets a notification from the server every time something of potential interest happens. Any event handler plugged into the event manager can match on events of interest, take action, or maybe simply pass the information on. Event handlers are Erlang modules implemented by the Common Test user according to the gen_event behaviour (see the OTP User's Guide and Reference Manual for more information).</p> <p>As already described, a Common Test server always starts an event manager. The server also plugs in a default event handler which has as its only purpose to relay notifications to a globally registered CT Master event manager (if a CT Master server is running in the system). The CT Master also spawns an event manager at startup. Event handlers plugged into this manager will receive the events from all the test nodes as well as information from the CT Master server itself.</p> <h3><a name="id79226">11.2 Usage</a></h3> <a name="usage"></a> <p>Event handlers may be installed by means of an <span class="code">event_handler</span> start flag (<span class="code">ct_run</span>) or option (<span class="code"><span class="bold_code"><a href="ct.html#run_test-1">ct:run_test/1</a></span></span>), where the argument specifies the names of one or more event handler modules. Example:</p> <p><span class="code">$ ct_run -suite test/my_SUITE -event_handler handlers/my_evh1 handlers/my_evh2 -pa $PWD/handlers</span></p> <p>Use the <span class="code">ct_run -event_handler_init</span> option instead of <span class="code">-event_handler</span> to pass start arguments to the event handler init function.</p> <p>All event handler modules must have gen_event behaviour. Note also that these modules must be precompiled, and that their locations must be added explicitly to the Erlang code server search path (like in the example).</p> <p>An event_handler tuple in the argument <span class="code">Opts</span> has the following definition (see also <span class="code"><span class="bold_code"><a href="ct.html#run_test-1">ct:run_test/1</a></span></span> in the reference manual):</p> <div class="example"><pre> {event_handler,EventHandlers} EventHandlers = EH | [EH] EH = atom() | {atom(),InitArgs} | {[atom()],InitArgs} InitArgs = [term()]</pre></div> <p>Example:</p> <div class="example"><pre> 1> ct:run_test([{suite,"test/my_SUITE"},{event_handler,[my_evh1,{my_evh2,[node()]}]}]).</pre></div> <p>This will install two event handlers for the <span class="code">my_SUITE</span> test. Event handler <span class="code">my_evh1</span> is started with <span class="code">[]</span> as argument to the init function. Event handler <span class="code">my_evh2</span> is started with the name of the current node in the init argument list.</p> <p>Event handlers can also be plugged in by means of <span class="bold_code"><a href="run_test_chapter.html#test_specifications">test specification</a></span> terms:</p> <p><span class="code">{event_handler, EventHandlers}</span>, or</p> <p><span class="code">{event_handler, EventHandlers, InitArgs}</span>, or</p> <p><span class="code">{event_handler, NodeRefs, EventHandlers}</span>, or</p> <p><span class="code">{event_handler, NodeRefs, EventHandlers, InitArgs}</span></p> <p><span class="code">EventHandlers</span> is a list of module names. Before a test session starts, the init function of each plugged in event handler is called (with the InitArgs list as argument or [] if no start arguments are given).</p> <p>To plug a handler into the CT Master event manager, specify <span class="code">master</span> as the node in <span class="code">NodeRefs</span>.</p> <p>For an event handler to be able to match on events, the module must include the header file <span class="code">ct_event.hrl</span>. An event is a record with the following definition:</p> <p><span class="code">#event{name, node, data}</span></p> <p><span class="code">name</span> is the label (type) of the event. <span class="code">node</span> is the name of the node the event has originated from (only relevant for CT Master event handlers). <span class="code">data</span> is specific for the particular event.</p> <a name="events"></a> <p><strong>General events:</strong></p> <ul> <li> <span class="code">#event{name = start_logging, data = LogDir}</span> <p><span class="code">LogDir = string()</span>, top level log directory for the test run.</p> <p>Indicates that the logging process of Common Test has started successfully and is ready to receive IO messages.</p> </li> <li> <span class="code">#event{name = stop_logging, data = []}</span> <p>Indicates that the logging process of Common Test has been shut down at the end of the test run. </p> </li> <li> <span class="code">#event{name = test_start, data = {StartTime,LogDir}}</span> <p><span class="code">StartTime = {date(),time()}</span>, test run start date and time.</p> <p><span class="code">LogDir = string()</span>, top level log directory for the test run.</p> <p>This event indicates that Common Test has finished initial preparations and will begin executing test cases. </p> </li> <li> <span class="code">#event{name = test_done, data = EndTime}</span> <p><span class="code">EndTime = {date(),time()}</span>, date and time the test run finished.</p> <p>This indicates that the last test case has been executed and Common Test is shutting down. </p> </li> <li> <span class="code">#event{name = start_info, data = {Tests,Suites,Cases}}</span> <p><span class="code">Tests = integer()</span>, the number of tests.</p> <p><span class="code">Suites = integer()</span>, the total number of suites.</p> <p><span class="code">Cases = integer() | unknown</span>, the total number of test cases.</p> <p>Initial test run information that can be interpreted as: "This test run will execute <span class="code">Tests</span> separate tests, in total containing <span class="code">Cases</span> number of test cases, in <span class="code">Suites</span> number of suites". Note that if a test case group with a repeat property exists in any test, the total number of test cases can not be calculated (unknown). </p> </li> <li> <span class="code">#event{name = tc_start, data = {Suite,FuncOrGroup}}</span> <p><span class="code">Suite = atom()</span>, name of the test suite.</p> <p><span class="code">FuncOrGroup = Func | {Conf,GroupName,GroupProperties}</span></p> <p><span class="code">Func = atom()</span>, name of test case or configuration function.</p> <p><span class="code">Conf = init_per_group | end_per_group</span>, group configuration function.</p> <p><span class="code">GroupName = atom()</span>, name of the group.</p> <p><span class="code">GroupProperties = list()</span>, list of execution properties for the group.</p> <p>This event informs about the start of a test case, or a group configuration function. The event is sent also for <span class="code">init_per_suite</span> and <span class="code">end_per_suite</span>, but not for <span class="code">init_per_testcase</span> and <span class="code">end_per_testcase</span>. If a group configuration function is starting, the group name and execution properties are also given. </p> </li> <li> <span class="code">#event{name = tc_logfile, data = {{Suite,Func},LogFileName}}</span> <p><span class="code">Suite = atom()</span>, name of the test suite.</p> <p><span class="code">Func = atom()</span>, name of test case or configuration function.</p> <p><span class="code">LogFileName = string()</span>, full name of test case log file.</p> <p>This event is sent at the start of each test case (and configuration function except <span class="code">init/end_per_testcase</span>) and carries information about the full name (i.e. the file name including the absolute directory path) of the current test case log file. </p> </li> <a name="tc_done"></a> <li> <span class="code">#event{name = tc_done, data = {Suite,FuncOrGroup,Result}}</span> <p><span class="code">Suite = atom()</span>, name of the suite.</p> <p><span class="code">FuncOrGroup = Func | {Conf,GroupName,GroupProperties}</span></p> <p><span class="code">Func = atom()</span>, name of test case or configuration function.</p> <p><span class="code">Conf = init_per_group | end_per_group</span>, group configuration function.</p> <p><span class="code">GroupName = unknown | atom()</span>, name of the group (unknown if init- or end function times out).</p> <p><span class="code">GroupProperties = list()</span>, list of execution properties for the group.</p> <p><span class="code">Result = ok | {skipped,SkipReason} | {failed,FailReason}</span>, the result.</p> <a name="skipreason"></a> <p><span class="code">SkipReason = {require_failed,RequireInfo} | {require_failed_in_suite0,RequireInfo} | {failed,{Suite,init_per_testcase,FailInfo}} | UserTerm</span>, the reason why the case has been skipped.</p> <a name="failreason"></a> <p><span class="code">FailReason = {error,FailInfo} | {error,{RunTimeError,StackTrace}} | {timetrap_timeout,integer()} | {failed,{Suite,end_per_testcase,FailInfo}}</span>, reason for failure.</p> <p><span class="code">RequireInfo = {not_available,atom() | tuple()}</span>, why require has failed.</p> <p><span class="code">FailInfo = {timetrap_timeout,integer()} | {RunTimeError,StackTrace} | UserTerm</span>, detailed information about an error.</p> <p><span class="code">RunTimeError = term()</span>, a run-time error, e.g. badmatch, undef, etc.</p> <p><span class="code">StackTrace = list()</span>, list of function calls preceeding a run-time error.</p> <p><span class="code">UserTerm = term()</span>, arbitrary data specified by user, or <span class="code">exit/1</span> info.</p> <p>This event informs about the end of a test case or a configuration function (see the <span class="code">tc_start</span> event for details on the FuncOrGroup element). With this event comes the final result of the function in question. It is possible to determine on the top level of <span class="code">Result</span> if the function was successful, skipped (by the user), or if it failed. It is of course possible to dig deeper and also perform pattern matching on the various reasons for skipped or failed. Note that <span class="code">{'EXIT',Reason}</span> tuples have been translated into <span class="code">{error,Reason}</span>. Note also that if a <span class="code">{failed,{Suite,end_per_testcase,FailInfo}</span> result is received, it actually means the test case was successful, but that <span class="code">end_per_testcase</span> for the case failed. </p> </li> <a name="tc_auto_skip"></a> <li> <span class="code">#event{name = tc_auto_skip, data = {Suite,Func,Reason}}</span> <p><span class="code">Suite = atom()</span>, the name of the suite.</p> <p><span class="code">Func = atom()</span>, the name of the test case or configuration function.</p> <p><span class="code">Reason = {failed,FailReason} | {require_failed_in_suite0,RequireInfo}</span>, reason for auto skipping <span class="code">Func</span>.</p> <p><span class="code">FailReason = {Suite,ConfigFunc,FailInfo}} | {Suite,FailedCaseInSequence}</span>, reason for failure.</p> <p><span class="code">RequireInfo = {not_available,atom() | tuple()}</span>, why require has failed.</p> <p><span class="code">ConfigFunc = init_per_suite | init_per_group</span></p> <p><span class="code">FailInfo = {timetrap_timeout,integer()} | {RunTimeError,StackTrace} | bad_return | UserTerm</span>, detailed information about an error.</p> <p><span class="code">FailedCaseInSequence = atom()</span>, name of a case that has failed in a sequence.</p> <p><span class="code">RunTimeError = term()</span>, a run-time error, e.g. badmatch, undef, etc.</p> <p><span class="code">StackTrace = list()</span>, list of function calls preceeding a run-time error.</p> <p><span class="code">UserTerm = term()</span>, arbitrary data specified by user, or <span class="code">exit/1</span> info.</p> <p>This event gets sent for every test case or configuration function that Common Test has skipped automatically because of either a failed <span class="code">init_per_suite</span> or <span class="code">init_per_group</span>, a failed <span class="code">require</span> in <span class="code">suite/0</span>, or a failed test case in a sequence. Note that this event is never received as a result of a test case getting skipped because of <span class="code">init_per_testcase</span> failing, since that information is carried with the <span class="code">tc_done</span> event. </p> </li> <a name="tc_user_skip"></a> <li> <span class="code">#event{name = tc_user_skip, data = {Suite,TestCase,Comment}}</span> <p><span class="code">Suite = atom()</span>, name of the suite.</p> <p><span class="code">TestCase = atom()</span>, name of the test case.</p> <p><span class="code">Comment = string()</span>, reason for skipping the test case.</p> <p>This event specifies that a test case has been skipped by the user. It is only ever received if the skip was declared in a test specification. Otherwise, user skip information is received as a <span class="code">{skipped,SkipReason}</span> result in the <span class="code">tc_done</span> event for the test case. </p> </li> <li> <span class="code">#event{name = test_stats, data = {Ok,Failed,Skipped}}</span> <p><span class="code">Ok = integer()</span>, the current number of successful test cases.</p> <p><span class="code">Failed = integer()</span>, the current number of failed test cases.</p> <p><span class="code">Skipped = {UserSkipped,AutoSkipped}</span></p> <p><span class="code">UserSkipped = integer()</span>, the current number of user skipped test cases.</p> <p><span class="code">AutoSkipped = integer()</span>, the current number of auto skipped test cases.</p> <p>This is a statistics event with the current count of successful, skipped and failed test cases so far. This event gets sent after the end of each test case, immediately following the <span class="code">tc_done</span> event. </p> </li> </ul> <p><strong>Internal events:</strong></p> <ul> <li> <span class="code">#event{name = start_make, data = Dir}</span> <p><span class="code">Dir = string()</span>, running make in this directory.</p> <p>An internal event saying that Common Test will start compiling modules in directory <span class="code">Dir</span>. </p> </li> <li> <span class="code">#event{name = finished_make, data = Dir}</span> <p><span class="code">Dir = string()</span>, finished running make in this directory.</p> <p>An internal event saying that Common Test is finished compiling modules in directory <span class="code">Dir</span>. </p> </li> <li> <span class="code">#event{name = start_write_file, data = FullNameFile}</span> <p><span class="code">FullNameFile = string(), full name of the file.</span></p> <p>An internal event used by the Common Test Master process to synchronize particular file operations. </p> </li> <li> <span class="code">#event{name = finished_write_file, data = FullNameFile}</span> <p><span class="code">FullNameFile = string(), full name of the file.</span></p> <p>An internal event used by the Common Test Master process to synchronize particular file operations. </p> </li> </ul> <p>The events are also documented in <span class="code">ct_event.erl</span>. This module may serve as an example of what an event handler for the CT event manager can look like.</p> <div class="note"> <div class="label">Note</div> <div class="content"><p><p>To ensure that printouts to standard out (or printouts made with <span class="code"><span class="bold_code"><a href="ct.html#log-2">ct:log/2/3</a></span></span> or <span class="code"><span class="bold_code"><a href="javascript:erlhref('../../../../doc/../','ct','pal-2.html');">ct:pal/2/3</a></span></span>) get written to the test case log file, and not to the Common Test framework log, you can syncronize with the Common Test server by matching on the <span class="code">tc_start</span> and <span class="code">tc_done</span> events. In the period between these events, all IO gets directed to the test case log file. These events are sent synchronously to avoid potential timing problems (e.g. that the test case log file gets closed just before an IO message from an external process gets through). Knowing this, you need to be careful that your <span class="code">handle_event/2</span> callback function doesn't stall the test execution, possibly causing unexpected behaviour as a result.</p></p></div> </div> </div> <div class="footer"> <hr> <p>Copyright © 2003-2012 Ericsson AB. All Rights Reserved.</p> </div> </div> </div></body> </html>