Sophie

Sophie

distrib > Fedora > 17 > i386 > media > updates > by-pkgid > 675c8c8167236dfcf8d66da674f931e8 > files > 1480

erlang-doc-R15B-03.3.fc17.noarch.rpm

<!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 -- test_server</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/test_server-3.5.3.pdf">PDF</a><br><a href="../../../../doc/index.html">Top</a></small><p><strong>Test Server</strong><br><strong>Reference Manual</strong><br><small>Version 3.5.3</small></p>
<br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Table of Contents</strong></small></p>
<ul class="flipMenu">
<li title="test_server (App)"><a href="test_server_app.html">test_server (App)
                </a></li>
<li id="no" title="test_server_ctrl " expanded="false">test_server_ctrl<ul>
<li><a href="test_server_ctrl.html">
                  Top of manual page
                </a></li>
<li title="start-0"><a href="test_server_ctrl.html#start-0">start/0</a></li>
<li title="start-1"><a href="test_server_ctrl.html#start-1">start/1</a></li>
<li title="stop-0"><a href="test_server_ctrl.html#stop-0">stop/0</a></li>
<li title="add_dir-2"><a href="test_server_ctrl.html#add_dir-2">add_dir/2</a></li>
<li title="add_dir-3"><a href="test_server_ctrl.html#add_dir-3">add_dir/3</a></li>
<li title="add_dir-2"><a href="test_server_ctrl.html#add_dir-2">add_dir/2</a></li>
<li title="add_dir-3"><a href="test_server_ctrl.html#add_dir-3">add_dir/3</a></li>
<li title="add_module-1"><a href="test_server_ctrl.html#add_module-1">add_module/1</a></li>
<li title="add_module-2"><a href="test_server_ctrl.html#add_module-2">add_module/2</a></li>
<li title="add_case-2"><a href="test_server_ctrl.html#add_case-2">add_case/2</a></li>
<li title="add_case-3"><a href="test_server_ctrl.html#add_case-3">add_case/3</a></li>
<li title="add_cases-2"><a href="test_server_ctrl.html#add_cases-2">add_cases/2</a></li>
<li title="add_cases-3"><a href="test_server_ctrl.html#add_cases-3">add_cases/3</a></li>
<li title="add_spec-1"><a href="test_server_ctrl.html#add_spec-1">add_spec/1</a></li>
<li title="add_dir_with_skip-3"><a href="test_server_ctrl.html#add_dir_with_skip-3">add_dir_with_skip/3</a></li>
<li title="add_dir_with_skip-4"><a href="test_server_ctrl.html#add_dir_with_skip-4">add_dir_with_skip/4</a></li>
<li title="add_module_with_skip-2"><a href="test_server_ctrl.html#add_module_with_skip-2">add_module_with_skip/2</a></li>
<li title="add_module_with_skip-3"><a href="test_server_ctrl.html#add_module_with_skip-3">add_module_with_skip/3</a></li>
<li title="add_case_with_skip-3"><a href="test_server_ctrl.html#add_case_with_skip-3">add_case_with_skip/3</a></li>
<li title="add_case_with_skip-4"><a href="test_server_ctrl.html#add_case_with_skip-4">add_case_with_skip/4</a></li>
<li title="add_cases_with_skip-3"><a href="test_server_ctrl.html#add_cases_with_skip-3">add_cases_with_skip/3</a></li>
<li title="add_cases_with_skip-4"><a href="test_server_ctrl.html#add_cases_with_skip-4">add_cases_with_skip/4</a></li>
<li title="add_tests_with_skip-3"><a href="test_server_ctrl.html#add_tests_with_skip-3">add_tests_with_skip/3</a></li>
<li title="abort_current_testcase-1"><a href="test_server_ctrl.html#abort_current_testcase-1">abort_current_testcase/1</a></li>
<li title="set_levels-3"><a href="test_server_ctrl.html#set_levels-3">set_levels/3</a></li>
<li title="get_levels-0"><a href="test_server_ctrl.html#get_levels-0">get_levels/0</a></li>
<li title="jobs-0"><a href="test_server_ctrl.html#jobs-0">jobs/0</a></li>
<li title="multiply_timetraps-1"><a href="test_server_ctrl.html#multiply_timetraps-1">multiply_timetraps/1</a></li>
<li title="scale_timetraps-1"><a href="test_server_ctrl.html#scale_timetraps-1">scale_timetraps/1</a></li>
<li title="get_timetrap_parameters-0"><a href="test_server_ctrl.html#get_timetrap_parameters-0">get_timetrap_parameters/0</a></li>
<li title="cover-2"><a href="test_server_ctrl.html#cover-2">cover/2</a></li>
<li title="cover-2"><a href="test_server_ctrl.html#cover-2">cover/2</a></li>
<li title="cover-3"><a href="test_server_ctrl.html#cover-3">cover/3</a></li>
<li title="cross_cover_analyse-1"><a href="test_server_ctrl.html#cross_cover_analyse-1">cross_cover_analyse/1</a></li>
<li title="trc-1"><a href="test_server_ctrl.html#trc-1">trc/1</a></li>
<li title="stop_trace-0"><a href="test_server_ctrl.html#stop_trace-0">stop_trace/0</a></li>
<li title="run_test-1"><a href="test_server_ctrl.html#run_test-1">run_test/1</a></li>
<li title="get_suite-2"><a href="test_server_ctrl.html#get_suite-2">get_suite/2</a></li>
<li title="init_tc-3"><a href="test_server_ctrl.html#init_tc-3">init_tc/3</a></li>
<li title="end_tc-3"><a href="test_server_ctrl.html#end_tc-3">end_tc/3</a></li>
<li title="report-2"><a href="test_server_ctrl.html#report-2">report/2</a></li>
<li title="error_notification-4"><a href="test_server_ctrl.html#error_notification-4">error_notification/4</a></li>
<li title="warn-1"><a href="test_server_ctrl.html#warn-1">warn/1</a></li>
<li title="target_info-0"><a href="test_server_ctrl.html#target_info-0">target_info/0</a></li>
</ul>
</li>
<li id="loadscrollpos" title="test_server " expanded="true">test_server<ul>
<li><a href="test_server.html">
                  Top of manual page
                </a></li>
<li title="os_type-0"><a href="test_server.html#os_type-0">os_type/0</a></li>
<li title="fail-0"><a href="test_server.html#fail-0">fail/0</a></li>
<li title="fail-1"><a href="test_server.html#fail-1">fail/1</a></li>
<li title="timetrap-1"><a href="test_server.html#timetrap-1">timetrap/1</a></li>
<li title="timetrap_cancel-1"><a href="test_server.html#timetrap_cancel-1">timetrap_cancel/1</a></li>
<li title="timetrap_scale_factor-0"><a href="test_server.html#timetrap_scale_factor-0">timetrap_scale_factor/0</a></li>
<li title="sleep-1"><a href="test_server.html#sleep-1">sleep/1</a></li>
<li title="adjusted_sleep-1"><a href="test_server.html#adjusted_sleep-1">adjusted_sleep/1</a></li>
<li title="hours-1"><a href="test_server.html#hours-1">hours/1</a></li>
<li title="minutes-1"><a href="test_server.html#minutes-1">minutes/1</a></li>
<li title="seconds-1"><a href="test_server.html#seconds-1">seconds/1</a></li>
<li title="format-1"><a href="test_server.html#format-1">format/1</a></li>
<li title="format-2"><a href="test_server.html#format-2">format/2</a></li>
<li title="format-2"><a href="test_server.html#format-2">format/2</a></li>
<li title="format-3"><a href="test_server.html#format-3">format/3</a></li>
<li title="capture_start-0"><a href="test_server.html#capture_start-0">capture_start/0</a></li>
<li title="capture_stop-0"><a href="test_server.html#capture_stop-0">capture_stop/0</a></li>
<li title="capture_get-0"><a href="test_server.html#capture_get-0">capture_get/0</a></li>
<li title="messages_get-0"><a href="test_server.html#messages_get-0">messages_get/0</a></li>
<li title="timecall-3"><a href="test_server.html#timecall-3">timecall/3</a></li>
<li title="do_times-4"><a href="test_server.html#do_times-4">do_times/4</a></li>
<li title="do_times-2"><a href="test_server.html#do_times-2">do_times/2</a></li>
<li title="m_out_of_n-3"><a href="test_server.html#m_out_of_n-3">m_out_of_n/3</a></li>
<li title="call_crash-3"><a href="test_server.html#call_crash-3">call_crash/3</a></li>
<li title="call_crash-4"><a href="test_server.html#call_crash-4">call_crash/4</a></li>
<li title="call_crash-5"><a href="test_server.html#call_crash-5">call_crash/5</a></li>
<li title="temp_name-1"><a href="test_server.html#temp_name-1">temp_name/1</a></li>
<li title="break-1"><a href="test_server.html#break-1">break/1</a></li>
<li title="continue-0"><a href="test_server.html#continue-0">continue/0</a></li>
<li title="run_on_shielded_node-2"><a href="test_server.html#run_on_shielded_node-2">run_on_shielded_node/2</a></li>
<li title="start_node-3"><a href="test_server.html#start_node-3">start_node/3</a></li>
<li title="stop_node-1"><a href="test_server.html#stop_node-1">stop_node/1</a></li>
<li title="is_commercial-0"><a href="test_server.html#is_commercial-0">is_commercial/0</a></li>
<li title="is_release_available-1"><a href="test_server.html#is_release_available-1">is_release_available/1</a></li>
<li title="is_native-1"><a href="test_server.html#is_native-1">is_native/1</a></li>
<li title="app_test-1"><a href="test_server.html#app_test-1">app_test/1</a></li>
<li title="app_test-2"><a href="test_server.html#app_test-2">app_test/2</a></li>
<li title="comment-1"><a href="test_server.html#comment-1">comment/1</a></li>
<li title="all-1"><a href="test_server.html#all-1">all/1</a></li>
<li title="init_per_suite-1"><a href="test_server.html#init_per_suite-1">init_per_suite/1</a></li>
<li title="end_per_suite-1"><a href="test_server.html#end_per_suite-1">end_per_suite/1</a></li>
<li title="init_per_testcase-2"><a href="test_server.html#init_per_testcase-2">init_per_testcase/2</a></li>
<li title="end_per_testcase-2"><a href="test_server.html#end_per_testcase-2">end_per_testcase/2</a></li>
<li title="Case-1"><a href="test_server.html#Case-1">Case/1</a></li>
<li title="Case-1"><a href="test_server.html#Case-1">Case/1</a></li>
<li title="Case-1"><a href="test_server.html#Case-1">Case/1</a></li>
</ul>
</li>
</ul>
</div></div>
<div id="content">
<div class="innertube">
<!-- refpage --><center><h1>test_server</h1></center>
  
  <h3>MODULE</h3>
<div class="REFBODY">test_server</div>
  <h3>MODULE SUMMARY</h3>
<div class="REFBODY">This module provides support for test suite authors.</div>
  <h3>DESCRIPTION</h3>
<div class="REFBODY"><p>
    <p>The <span class="code">test_server</span> module aids the test suite author by providing
      various support functions. The supported functionality includes:
      </p>
    <ul>
      <li>Logging and timestamping
      </li>
      <li>Capturing output to stdout
      </li>
      <li>Retrieving and flushing the message queue of a process
      </li>
      <li>Watchdog timers, process sleep, time measurement and unit
       conversion
      </li>
      <li>Private scratch directory for all test suites
      </li>
      <li>Start and stop of slave- or peer nodes</li>
    </ul>
    <p>For more information on how to write test cases and for
      examples, please see the Test Server User's Guide. 
      </p>
  </p></div>

  <h3><a name="id67542">TEST SUITE SUPPORT FUNCTIONS</a></h3>
<div class="REFBODY">
    
    <p>The following functions are supposed to be used inside a test
      suite.
      </p>
  </div>
  <h3>EXPORTS</h3>
    <p><a name="os_type-0"><span class="bold_code">os_type() -&gt; OSType</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">OSType = term()</span><br>
</div>
        <div class="REFBODY">This is the same as returned from <span class="code">os:type/0</span>
</div>
      </div>
<div class="REFBODY"><p>
        <p>This function can be called on controller or target node, and
          it will always return the OS type of the target node.</p>
      </p></div>
    <p><a name="fail-0"><span class="bold_code">fail()</span></a><br><a name="fail-1"><span class="bold_code">fail(Reason)</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Reason = term()</span><br>
</div>
        <div class="REFBODY">The reason why the test case failed.</div>
      </div>
<div class="REFBODY"><p>
        <p>This will make the test suite fail with a given reason, or
          with <span class="code">suite_failed</span> if no reason was given. Use this
          function if you want to terminate a test case, as this will
          make it easier to read the log- and HTML files. <span class="code">Reason</span>
          will appear in the comment field in the HTML log.</p>
      </p></div>
    <p><a name="timetrap-1"><span class="bold_code">timetrap(Timout) -&gt; Handle</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Timeout = integer() | {hours,H} | {minutes,M} | {seconds,S}</span><br>
</div>
        <div class="REFTYPES">
<span class="bold_code">H = M = S = integer()</span><br>
</div>
        <div class="REFTYPES">
<span class="bold_code">Pid = pid()</span><br>
</div>
        <div class="REFBODY">The process that is to be timetrapped (<span class="code">self()</span>by default)</div>
      </div>
<div class="REFBODY"><p>
        <p>Sets up a time trap for the current process. An expired
          timetrap kills the process with reason
          <span class="code">timetrap_timeout</span>. The returned handle is to be given
          as argument to <span class="code">timetrap_cancel</span> before the timetrap
          expires.  If <span class="code">Timeout</span> is an integer, it is expected to
          be milliseconds.</p>
        <div class="note">
<div class="label">Note</div>
<div class="content"><p>
          <p>If the current process is trapping exits, it will not be killed
            by the exit signal with reason <span class="code">timetrap_timeout</span>.
            If this happens, the process will be sent an exit signal
            with reason <span class="code">kill</span> 10 seconds later which will kill the
            process. Information about the timetrap timeout will in
            this case not be found in the test logs. However, the
            error_logger will be sent a warning.</p>
        </p></div>
</div>
      </p></div>
    <p><a name="timetrap_cancel-1"><span class="bold_code">timetrap_cancel(Handle) -&gt; ok</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Handle = term()</span><br>
</div>
        <div class="REFBODY">Handle returned from <span class="code">timetrap</span>
</div>
      </div>
<div class="REFBODY"><p>
        <p>This function cancels a timetrap. This must be done before
          the timetrap expires.</p>
      </p></div>
    <p><a name="timetrap_scale_factor-0"><span class="bold_code">timetrap_scale_factor() -&gt; ScaleFactor</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">ScaleFactor = integer()</span><br>
</div>
      </div>
<div class="REFBODY"><p>
        <p>This function returns the scale factor by which all timetraps
	are scaled. It is normally 1, but can be greater than 1 if
	the test_server is running <span class="code">cover</span>, using a larger amount of
	scheduler threads than the amount of logical processors on the
	system, running under purify, valgrind or in a debug-compiled
	emulator. The scale factor can be used if you need to scale you
	own timeouts in test cases with same factor as the test_server
	uses.</p>
      </p></div>
    <p><a name="sleep-1"><span class="bold_code">sleep(MSecs) -&gt; ok</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">MSecs = integer() | float() | infinity</span><br>
</div>
        <div class="REFBODY">The number of milliseconds to sleep</div>
      </div>
<div class="REFBODY"><p>
        <p>This function suspends the calling process for at least the
          supplied number of milliseconds. There are two major reasons
          why you should use this function instead of
          <span class="code">timer:sleep</span>, the first being that the module
          <span class="code">timer</span> may be unavailable at the time the test suite is
          run, and the second that it also accepts floating point
          numbers.</p>
      </p></div>
    <p><a name="adjusted_sleep-1"><span class="bold_code">adjusted_sleep(MSecs) -&gt; ok</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">MSecs = integer() | float() | infinity</span><br>
</div>
        <div class="REFBODY">The default number of milliseconds to sleep</div>
      </div>
<div class="REFBODY"><p>
        <p>This function suspends the calling process for at least the
          supplied number of milliseconds. The function behaves the same
	  way as <span class="code">test_server:sleep/1</span>, only <span class="code">MSecs</span>
	  will be multiplied by the 'multiply_timetraps' value, if set,
	  and also automatically scaled up if 'scale_timetraps' is set
	  to true (which it is by default).</p>
      </p></div>
    <p><a name="hours-1"><span class="bold_code">hours(N) -&gt; MSecs</span></a><br><a name="minutes-1"><span class="bold_code">minutes(N) -&gt; MSecs</span></a><br><a name="seconds-1"><span class="bold_code">seconds(N) -&gt; MSecs</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">N = integer()</span><br>
</div>
        <div class="REFBODY">Value to convert to milliseconds.</div>
      </div>
<div class="REFBODY"><p>
        <p>Theese functions convert <span class="code">N</span> number of hours, minutes
          or seconds into milliseconds.
          </p>
        <p>Use this function when you want to
          <span class="code">test_server:sleep/1</span> for a number of seconds, minutes or
          hours(!).</p>
      </p></div>
    <p><a name="format-1"><span class="bold_code">format(Format) -&gt; ok</span></a><br><a name="format-2"><span class="bold_code">format(Format, Args)</span></a><br><a name="format-2"><span class="bold_code">format(Pri, Format)</span></a><br><a name="format-3"><span class="bold_code">format(Pri, Format, Args)</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Format = string()</span><br>
</div>
        <div class="REFBODY">Format as described for <span class="code">io_:format</span>.</div>
        <div class="REFTYPES">
<span class="bold_code">Args = list()</span><br>
</div>
        <div class="REFBODY">List of arguments to format.</div>
      </div>
<div class="REFBODY"><p>
        <p>Formats output just like <span class="code">io:format</span> but sends the
          formatted string to a logfile. If the urgency value,
          <span class="code">Pri</span>, is lower than some threshold value, it will also
          be written to the test person's console. Default urgency is
          50, default threshold for display on the console is 1.
          </p>
        <p>Typically, the test person don't want to see everything a
          test suite outputs, but is merely interested in if the test
          cases succeeded or not, which the test server tells him. If he
          would like to see more, he could manually change the threshold
          values by using the <span class="code">test_server_ctrl:set_levels/3</span>
          function.</p>
      </p></div>
    <p><a name="capture_start-0"><span class="bold_code">capture_start() -&gt; ok</span></a><br><a name="capture_stop-0"><span class="bold_code">capture_stop() -&gt; ok</span></a><br><a name="capture_get-0"><span class="bold_code">capture_get() -&gt; list()</span></a><br></p>
<div class="REFBODY"><p>
        <p>These functions makes it possible to capture all output to
          stdout from a process started by the test suite. The list of
          characters captured can be purged by using <span class="code">capture_get</span>.</p>
      </p></div>
    <p><a name="messages_get-0"><span class="bold_code">messages_get() -&gt; list()</span></a><br></p>
<div class="REFBODY"><p>
        <p>This function will empty and return all the messages
          currently in the calling process' message queue.</p>
      </p></div>
    <p><a name="timecall-3"><span class="bold_code">timecall(M, F, A) -&gt; {Time, Value}</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">M = atom()</span><br>
</div>
        <div class="REFBODY">The name of the module where the function resides.</div>
        <div class="REFTYPES">
<span class="bold_code">F = atom()</span><br>
</div>
        <div class="REFBODY">The name of the function to call in the module.</div>
        <div class="REFTYPES">
<span class="bold_code">A = list()</span><br>
</div>
        <div class="REFBODY">The arguments to supply the called function.</div>
        <div class="REFTYPES">
<span class="bold_code">Time = integer()</span><br>
</div>
        <div class="REFBODY">The number of seconds it took to call the function.</div>
        <div class="REFTYPES">
<span class="bold_code">Value = term()</span><br>
</div>
        <div class="REFBODY">Value returned from the called function.</div>
      </div>
<div class="REFBODY"><p>
        <p>This function measures the time (in seconds) it takes to
          call a certain function. The function call is <strong>not</strong>
          caught within a catch.</p>
      </p></div>
    <p><a name="do_times-4"><span class="bold_code">do_times(N, M, F, A) -&gt; ok</span></a><br><a name="do_times-2"><span class="bold_code">do_times(N, Fun)</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">N = integer()</span><br>
</div>
        <div class="REFBODY">Number of times to call MFA.</div>
        <div class="REFTYPES">
<span class="bold_code">M = atom()</span><br>
</div>
        <div class="REFBODY">Module name where the function resides.</div>
        <div class="REFTYPES">
<span class="bold_code">F = atom()</span><br>
</div>
        <div class="REFBODY">Function name to call.</div>
        <div class="REFTYPES">
<span class="bold_code">A = list()</span><br>
</div>
        <div class="REFBODY">Arguments to M:F.</div>
      </div>
<div class="REFBODY"><p>
        <p>Calls MFA or Fun N times. Useful for extensive testing of a
          sensitive function.</p>
      </p></div>
    <p><a name="m_out_of_n-3"><span class="bold_code">m_out_of_n(M, N, Fun) -&gt; ok | exit({m_out_of_n_failed, {R,left_to_do}}</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">N = integer()</span><br>
</div>
        <div class="REFBODY">Number of times to call the Fun.</div>
        <div class="REFTYPES">
<span class="bold_code">M = integer()</span><br>
</div>
        <div class="REFBODY">Number of times to require a successful return.</div>
      </div>
<div class="REFBODY"><p>
        <p>Repeatedly evaluates the given function until it succeeds
          (doesn't crash) M times. If, after N times, M successful
          attempts have not been accomplished, the process crashes with
          reason {m_out_of_n_failed, {R,left_to_do}}, where R indicates
          how many cases that was still to be successfully completed.
          </p>
        <p>For example:
          </p>
        <p><span class="code">m_out_of_n(1,4,fun() -&gt; tricky_test_case() end)</span>          <br>
Tries to run tricky_test_case() up to 4 times, and is
          happy if it succeeds once.
          </p>
        <p><span class="code">m_out_of_n(7,8,fun() -&gt; clock_sanity_check() end)</span>          <br>
Tries running clock_sanity_check() up to 8 times,and
          allows the function to fail once.  This might be useful if
          clock_sanity_check/0 is known to fail if the clock crosses an
          hour boundary during the test (and the up to 8 test runs could
          never cross 2 boundaries)</p>
      </p></div>
    <p><a name="call_crash-3"><span class="bold_code">call_crash(M, F, A) -&gt; Result</span></a><br><a name="call_crash-4"><span class="bold_code">call_crash(Time, M, F, A) -&gt; Result</span></a><br><a name="call_crash-5"><span class="bold_code">call_crash(Time, Crash, M, F, A) -&gt; Result</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Result = ok | exit(call_crash_timeout) | exit({wrong_crash_reason, Reason})</span><br>
</div>
        <div class="REFTYPES">
<span class="bold_code">Crash = term()</span><br>
</div>
        <div class="REFBODY">Crash return from the function.</div>
        <div class="REFTYPES">
<span class="bold_code">Time = integer()</span><br>
</div>
        <div class="REFBODY">Timeout in milliseconds.</div>
        <div class="REFTYPES">
<span class="bold_code">M = atom()</span><br>
</div>
        <div class="REFBODY">Module name where the function resides.</div>
        <div class="REFTYPES">
<span class="bold_code">F = atom()</span><br>
</div>
        <div class="REFBODY">Function name to call.</div>
        <div class="REFTYPES">
<span class="bold_code">A = list()</span><br>
</div>
        <div class="REFBODY">Arguments to M:F.</div>
      </div>
<div class="REFBODY"><p>
        <p>Spawns a new process that calls MFA. The call is considered
          successful if the call crashes with the gives reason
          (<span class="code">Crash</span>) or any reason if not specified. The call must
          terminate within the given time (default <span class="code">infinity</span>), or
          it is considered a failure.</p>
      </p></div>
    <p><a name="temp_name-1"><span class="bold_code">temp_name(Stem) -&gt; Name</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Stem = string()</span><br>
</div>
      </div>
<div class="REFBODY"><p>
        <p>Returns a unique filename starting with <span class="code">Stem</span> with
          enough extra characters appended to make up a unique
          filename. The filename returned is guaranteed not to exist in
          the filesystem at the time of the call.</p>
      </p></div>
    <p><a name="break-1"><span class="bold_code">break(Comment) -&gt; ok</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Comment = string()</span><br>
</div>
      </div>
<div class="REFBODY"><p>
        <p><span class="code">Comment</span> is a string which will be written in
          the shell, e.g. explaining what to do.</p>
        <p>This function will cancel all timetraps and pause the
          execution of the test case until the user executes the
          <span class="code">continue/0</span> function. It gives the user the opportunity
          to interact with the erlang node running the tests, e.g. for
          debugging purposes or for manually executing a part of the
          test case.</p>
        <p>When the <span class="code">break/1</span> function is called, the shell will
          look something like this:</p>
        <div class="example"><pre>
   --- SEMIAUTOMATIC TESTING ---
   The test case executes on process &lt;0.51.0&gt;


   "Here is a comment, it could e.g. instruct to pull out a card"


   -----------------------------

   Continue with --&gt; test_server:continue().        </pre></div>
        <p>The user can now interact with the erlang node, and when
          ready call <span class="code">test_server:continue().</span></p>
        <p>Note that this function can not be used if the test is
          executed with <span class="code">ts:run/0/1/2/3/4</span> in <span class="code">batch</span> mode.</p>
      </p></div>
    <p><a name="continue-0"><span class="bold_code">continue() -&gt; ok</span></a><br></p>
<div class="REFBODY"><p>
        <p>This function must be called in order to continue after a
          test case has called <span class="code">break/1</span>.</p>
      </p></div>
    <p><a name="run_on_shielded_node-2"><span class="bold_code">run_on_shielded_node(Fun, CArgs) -&gt; term()</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Fun = function() (arity 0)</span><br>
</div>
        <div class="REFBODY">Function to execute on the shielded node.</div>
        <div class="REFTYPES">
<span class="bold_code">CArg = string()</span><br>
</div>
        <div class="REFBODY">Extra command line arguments to use when starting the shielded node.</div>
      </div>
<div class="REFBODY"><p>
        <p><span class="code">Fun</span> is executed in a process on a temporarily created
          hidden node with a proxy for communication with the test server
          node. The node is called a shielded node (should have been called
          a shield node). If <span class="code">Fun</span> is successfully executed, the result
          is returned. A peer node (see <span class="code">start_node/3</span>) started from
          the shielded node will be shielded from test server node, i.e.
          they will not be aware of each other. This is useful when you want
          to start nodes from earlier OTP releases than the OTP release of
          the test server node.</p>
        <p>Nodes from an earlier OTP release can normally not be started
          if the test server hasn't been started in compatibility mode
          (see the <span class="code">+R</span> flag in the <span class="code">erl(1)</span> documentation) of
          an earlier release. If a shielded node is started in compatibility
          mode of an earlier OTP release than the OTP release of the test
          server node, the shielded node can start nodes of an earlier OTP
          release.</p>
        <div class="note">
<div class="label">Note</div>
<div class="content"><p>
          <p>You <strong>must</strong> make sure that nodes started by the shielded
            node never communicate directly with the test server node.</p>
        </p></div>
</div>
        <div class="note">
<div class="label">Note</div>
<div class="content"><p>
          <p>Slave nodes always communicate with the test server node;
            therefore, <strong>never</strong> start <strong>slave nodes</strong> from the
            shielded node, <strong>always</strong> start <strong>peer nodes</strong>.</p>
        </p></div>
</div>
      </p></div>
    <p><a name="start_node-3"><span class="bold_code">start_node(Name, Type, Options) -&gt; {ok, Node} | {error, Reason}</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Name = atom() | string()</span><br>
</div>
        <div class="REFBODY">Name of the slavenode to start (as given to -sname or -name)</div>
        <div class="REFTYPES">
<span class="bold_code">Type = slave | peer</span><br>
</div>
        <div class="REFBODY">The type of node to start.</div>
        <div class="REFTYPES">
<span class="bold_code">Options = [{atom(), term()]</span><br>
</div>
        <div class="REFBODY">Tuplelist of options</div>
      </div>
<div class="REFBODY"><p>
        <p>This functions starts a node, possibly on a remote machine,
          and guarantees cross architecture transparency. Type is set to
          either <span class="code">slave</span> or <span class="code">peer</span>.
          </p>
        <p><span class="code">slave</span> means that the new node will have a master,
          i.e. the slave node will terminate if the master terminates,
          TTY output produced on the slave will be sent back to the
          master node and file I/O is done via the master. The master is
          normally the target node unless the target is itself a slave.
          </p>
        <p><span class="code">peer</span> means that the new node is an independent node
          with no master.
          </p>
        <p><span class="code">Options</span> is a tuplelist which can contain one or more
          of
          </p>
        <dl>
          <dt><strong><span class="code">{remote, true}</span></strong></dt>
          <dd>Start the node on a remote host. If not specified, the
           node will be started on the local host (with some
           exceptions, as for the case of VxWorks, where
           all nodes are started on a remote host).  Test cases that
           require a remote host will fail with a reasonable comment if
           no remote hosts are available at the time they are run.
          </dd>
          <dt><strong><span class="code">{args, Arguments}</span></strong></dt>
          <dd>Arguments passed directly to the node. This is
           typically a string appended to the command line.
          </dd>
          <dt><strong><span class="code">{wait, false}</span></strong></dt>
          <dd>Don't wait until the node is up. By default, this
           function does not return until the node is up and running,
           but this option makes it return as soon as the node start
           command is given..
                    <br>
Only valid for peer nodes
          </dd>
          <dt><strong><span class="code">{fail_on_error, false}</span></strong></dt>
          <dd>Returns <span class="code">{error, Reason}</span> rather than failing the
           test case.
                    <br>
Only valid for peer nodes. Note that slave nodes always
           act as if they had <span class="code">fail_on_error=false</span>
</dd>
          <dt><strong><span class="code">{erl, ReleaseList}</span></strong></dt>
          <dd>Use an Erlang emulator determined by ReleaseList when
           starting nodes, instead of the same emulator as the test
           server is running. ReleaseList is a list of specifiers,
           where a specifier is either {release, Rel}, {prog, Prog}, or
           'this'. Rel is either the name of a release, e.g., "r12b_patched"
           or 'latest'. 'this' means using the same emulator as the test
           server. Prog is the name of an emulator executable.  If the
           list has more than one element, one of them is picked
           randomly.  (Only works on Solaris and Linux, and the test server 
           gives warnings when it notices that nodes are not of the same
           version as itself.)
                    <br>
          <br>

           When specifying this option to run a previous release, use
          <span class="code">is_release_available/1</span> function to test if the given
           release is available and skip the test case if not.
                    <br>
          <br>

           In order to avoid compatibility problems (may not appear right
           away), use a shielded node (see <span class="code">run_on_shielded_node/2</span>)
           when starting nodes from different OTP releases than the test
           server.
          </dd>
          <dt><strong><span class="code">{cleanup, false}</span></strong></dt>
          <dd>Tells the test server not to kill this node if it is
           still alive after the test case is completed. This is useful
           if the same node is to be used by a group of test cases.
          </dd>
          <dt><strong><span class="code">{env, Env}</span></strong></dt>
          <dd>
<span class="code">Env</span> should be a list of tuples <span class="code">{Name, Val}</span>,
           where <span class="code">Name</span> is the name of an environment variable, and
          <span class="code">Val</span> is the value it is to have in the started node.
           Both <span class="code">Name</span> and <span class="code">Val</span> must be strings. The one
           exception is <span class="code">Val</span> being the atom <span class="code">false</span> (in
           analogy  with  <span class="code">os:getenv/1</span>),  which  removes  the
           environment variable. Only valid for peer nodes. Not
           available on VxWorks.</dd>
        </dl>
      </p></div>
    <p><a name="stop_node-1"><span class="bold_code">stop_node(NodeName) -&gt; bool()</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">NodeName = term()</span><br>
</div>
        <div class="REFBODY">Name of the node to stop</div>
      </div>
<div class="REFBODY"><p>
        <p>This functions stops a node previously started with
          <span class="code">start_node/3</span>. Use this function to stop any node you
          start, or the test server will produce a warning message in
          the test logs, and kill the nodes automatically unless it was
          started with the <span class="code">{cleanup, false}</span> option.</p>
      </p></div>
    <p><a name="is_commercial-0"><span class="bold_code">is_commercial() -&gt; bool()</span></a><br></p>
<div class="REFBODY"><p>
        <p>This function test whether the emulator is commercially supported
	emulator. The tests for a commercially supported emulator could be more
	stringent (for instance, a commercial release should always contain
	documentation for all applications).</p>
      </p></div>

    <p><a name="is_release_available-1"><span class="bold_code">is_release_available(Release) -&gt; bool()</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Release = string() | atom()</span><br>
</div>
        <div class="REFBODY">Release to test for</div>
      </div>
<div class="REFBODY"><p>
        <p>This function test whether the release given by
          <span class="code">Release</span> (for instance, "r12b_patched") is available
          on the computer that the test_server controller is running on.
          Typically, you should skip the test case if not.</p>
        <p>Caution: This function may not be called from the <span class="code">suite</span>
          clause of a test case, as the test_server will deadlock.</p>
      </p></div>
    <p><a name="is_native-1"><span class="bold_code">is_native(Mod) -&gt; bool()</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Mod = atom()</span><br>
</div>
        <div class="REFBODY">A module name</div>
      </div>
<div class="REFBODY"><p>
        <p>Checks whether the module is natively compiled or not</p>
      </p></div>
    <p><a name="app_test-1"><span class="bold_code">app_test(App) -&gt; ok | test_server:fail()</span></a><br><a name="app_test-2"><span class="bold_code">app_test(App,Mode)</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">App = term()</span><br>
</div>
        <div class="REFBODY">The name of the application to test</div>
        <div class="REFTYPES">
<span class="bold_code">Mode = pedantic | tolerant</span><br>
</div>
        <div class="REFBODY">Default is pedantic</div>
      </div>
<div class="REFBODY"><p>
        <p>Checks an applications .app file for obvious errors.
          The following is checked:
          </p>
        <ul>
          <li>required fields
          </li>
          <li>that all modules specified actually exists
          </li>
          <li>that all requires applications exists
          </li>
          <li>that no module included in the application has export_all
          </li>
          <li>that all modules in the ebin/ dir is included (If
          <span class="code">Mode==tolerant</span> this only produces a warning, as all
           modules does not have to be included)</li>
        </ul>
      </p></div>
    <p><a name="comment-1"><span class="bold_code">comment(Comment) -&gt; ok</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Comment = string()</span><br>
</div>
      </div>
<div class="REFBODY"><p>
        <p>The given String will occur in the comment field of the
          table on the HTML result page. If called several times, only
          the last comment is printed.  comment/1 is also overwritten by
          the return value {comment,Comment} from a test case or by
          fail/1 (which prints Reason as a comment).</p>
      </p></div>
  

  <h3><a name="id70176">TEST SUITE EXPORTS</a></h3>
<div class="REFBODY">
    
    <p>The following functions must be exported from a test suite
      module.
      </p>
  </div>
  <h3>EXPORTS</h3>
    <p><a name="all-1"><span class="bold_code">all(suite) -&gt; TestSpec | {skip, Comment}</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">TestSpec = list()</span><br>
</div>
        <div class="REFTYPES">
<span class="bold_code">Comment = string()</span><br>
</div>
        <div class="REFBODY">This comment will be printed on the HTML result page</div>
      </div>
<div class="REFBODY"><p>
        <p>This function must return the test specification for the
          test suite module. The syntax of a test specification is
          described in the Test Server User's Guide.</p>
      </p></div>
    <p><a name="init_per_suite-1"><span class="bold_code">init_per_suite(Config0) -&gt; Config1 | {skip, Comment}</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Config0 = Config1 = [tuple()]</span><br>
</div>
        <div class="REFTYPES">
<span class="bold_code">Comment = string()</span><br>
</div>
	<div class="REFBODY">Describes why the suite is skipped</div>
      </div>
<div class="REFBODY"><p>
        <p>This function is called before all other test cases in the
          suite. <span class="code">Config</span> is the configuration which can be modified
          here. Whatever is returned from this function is given as
          <span class="code">Config</span> to the test cases.
          </p>
        <p>If this function fails, all test cases in the suite will be
          skipped.</p>
      </p></div>
    <p><a name="end_per_suite-1"><span class="bold_code">end_per_suite(Config) -&gt; void()</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Config = [tuple()]</span><br>
</div>
      </div>
<div class="REFBODY"><p>
        <p>This function is called after the last test case in the
          suite, and can be used to clean up whatever the test cases
          have done. The return value is ignored.</p>
      </p></div>
    <p><a name="init_per_testcase-2"><span class="bold_code">init_per_testcase(Case, Config0) -&gt; Config1 | {skip, Comment}</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Case = atom()</span><br>
</div>
        <div class="REFTYPES">
<span class="bold_code">Config0 = Config1 = [tuple()]</span><br>
</div>
        <div class="REFTYPES">
<span class="bold_code">Comment = string()</span><br>
</div>
	<div class="REFBODY">Describes why the test case is skipped</div>
      </div>
<div class="REFBODY"><p>
        <p>This function is called before each test case. The
          <span class="code">Case</span> argument is the name of the test case, and
          <span class="code">Config</span> is the configuration which can be modified
          here. Whatever is returned from this function is given as
          <span class="code">Config</span> to the test case.</p>
      </p></div>
    <p><a name="end_per_testcase-2"><span class="bold_code">end_per_testcase(Case, Config) -&gt; void()</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Case = atom()</span><br>
</div>
        <div class="REFTYPES">
<span class="bold_code">Config = [tuple()]</span><br>
</div>
      </div>
<div class="REFBODY"><p>
        <p>This function is called after each test case, and can be
          used to clean up whatever the test case has done. The return
          value is ignored.</p>
      </p></div>
    <p><a name="Case-1"><span class="bold_code">Case(doc) -&gt; [Decription]</span></a><br><a name="Case-1"><span class="bold_code">Case(suite) -&gt; [] | TestSpec | {skip, Comment}</span></a><br><a name="Case-1"><span class="bold_code">Case(Config) -&gt; {skip, Comment} | {comment, Comment} | Ok</span></a><br></p>
<div class="REFBODY">
<p>Types:</p>
        <div class="REFTYPES">
<span class="bold_code">Description = string()</span><br>
</div>
        <div class="REFBODY">Short description of the test case</div>
        <div class="REFTYPES">
<span class="bold_code">TestSpec = list()</span><br>
</div>
        <div class="REFTYPES">
<span class="bold_code">Comment = string()</span><br>
</div>
        <div class="REFBODY">This comment will be printed on the HTML result page</div>
        <div class="REFTYPES">
<span class="bold_code">Ok = term()</span><br>
</div>
        <div class="REFTYPES">
<span class="bold_code">Config = [tuple()]</span><br>
</div>
        <div class="REFBODY">Elements from the Config parameter can be read with the ?config macro, see section about test suite support macros</div>
      </div>
<div class="REFBODY"><p>
        <p>The <strong>documentation clause</strong> (argument <span class="code">doc</span>) can
          be used for automatic generation of test documentation or test
          descriptions.
          </p>
        <p>The <strong>specification clause</strong> (argument <span class="code">spec</span>)
          shall return an empty list, the test specification for the
          test case or <span class="code">{skip,Comment}</span>. The syntax of a test
          specification is described in the Test Server User's Guide.
          </p>
        <p><strong>Note that the specification clause always is executed on the controller host.</strong></p>
        <p>The <strong>execution clause</strong> (argument <span class="code">Config</span>) is
          only called if the specification clause returns an empty list.
          The execution clause is the real test case. Here you must call
          the functions you want to test, and do whatever you need to
          check the result. If something fails, make sure the process
          crashes or call <span class="code">test_server:fail/0/1</span> (which also will
          cause the process to crash).
          </p>
        <p>You can return <span class="code">{skip,Comment}</span> if you decide not to
          run the test case after all, e.g. if it is not applicable on
          this platform.
          </p>
        <p>You can return <span class="code">{comment,Comment}</span> if you wish to
          print some information in the 'Comment' field on the HTML
          result page.
          </p>
        <p>If the execution clause returns anything else, it is
          considered a success, unless it is <span class="code">{'EXIT',Reason}</span> or
          <span class="code">{'EXIT',Pid,Reason}</span> which can't be distinguished from a
          crash, and thus will be considered a failure.
          </p>
        <p>A <strong>conf test case</strong> is a group of test cases with an
          init and a cleanup function. The init and cleanup functions
          are also test cases, but they have special rules:</p>
	  <ul>
	  <li>They do not need a specification clause.</li>
	  <li>They must always have the execution clause.</li>
	  <li>They must return the <span class="code">Config</span> parameter, a modified
          version of it or <span class="code">{skip,Comment}</span> from the execution clause.</li>
	  <li>The cleanup function may also return a tuple 
	  <span class="code">{return_group_result,Status}</span>, which is used to return the
	  status of the conf case to Test Server and/or to a conf case on a
	  higher level. (<span class="code">Status = ok | skipped | failed</span>).</li>
	  <li>
<span class="code">init_per_testcase</span> and <span class="code">end_per_testcase</span> are
          not called before and after these functions.</li>
	  </ul>
      </p></div>
  

  <h3><a name="id70580">TEST SUITE LINE NUMBERS</a></h3>
<div class="REFBODY">
    
    <p>If a test case fails, the test server can report the exact line
      number at which it failed. There are two ways of doing this,
      either by using the <span class="code">line</span> macro or by using the
      <span class="code">test_server_line</span> parse transform.
      </p>
    <p>The <span class="code">line</span> macro is described under TEST SUITE SUPPORT
      MACROS below. The <span class="code">line</span> macro will only report the last line
      executed when a test case failed.
      </p>
    <p>The <span class="code">test_server_line</span> parse transform is activated by
      including the headerfile <span class="code">test_server_line.hrl</span> in the test
      suite. When doing this, it is important that the
      <span class="code">test_server_line</span> module is in the code path of the erlang
      node compiling the test suite. The parse transform will report a
      history of a maximum of 10 lines when a test case
      fails. Consecutive lines in the same function are not shown.
      </p>
    <p>The attribute <span class="code">-no_lines(FuncList).</span> can be used in the
      test suite to exclude specific functions from the parse
      transform. This is necessary e.g. for functions that are executed
      on old (i.e. &lt;R10B) OTP releases. <span class="code">FuncList = [{Func,Arity}]</span>.
      </p>
    <p>If both the <span class="code">line</span> macro and the parse transform is used in
      the same module, the parse transform will overrule the macro.
      </p>
  </div>

  <h3><a name="id70651">TEST SUITE SUPPORT MACROS</a></h3>
<div class="REFBODY">
    
    <p>There are some macros defined in the <span class="code">test_server.hrl</span>
      that are quite useful for test suite programmers:
      </p>
    <p>The <strong>line</strong> macro, is quite
      essential when writing test cases. It tells the test server
      exactly what line of code that is being executed, so that it can
      report this line back if the test case fails. Use this macro at
      the beginning of every test case line of code.
      </p>
    <p>The <strong>config</strong> macro, is used to
      retrieve information from the <span class="code">Config</span> variable sent to all
      test cases. It is used with two arguments, where the first is the
      name of the configuration variable you wish to retrieve, and the
      second is the <span class="code">Config</span> variable supplied to the test case
      from the test server.
      </p>
    <p>Possible configuration variables include:</p>
    <ul>
      <li>
<span class="code">data_dir</span>  - Data file directory.</li>
      <li>
<span class="code">priv_dir</span>  - Scratch file directory.</li>
      <li>
<span class="code">nodes</span>     - Nodes specified in the spec file</li>
      <li>
<span class="code">nodenames</span> - Generated nodenames.</li>
      <li>Whatever added by conf test cases or
      <span class="code">init_per_testcase/2</span>
</li>
    </ul>
    <p>Examples of the <span class="code">line</span> and <span class="code">config</span> macros can be
      seen in the Examples chapter in the user's guide.
      </p>
    <p>If the <span class="code">line_trace</span> macro is defined, you will get a
      timestamp (<span class="code">erlang:now()</span>) in your minor log for each
      <span class="code">line</span> macro in your suite. This way you can at any time see
      which line is currently being executed, and when the line was
      called.
      </p>
    <p>The <span class="code">line_trace</span> macro can also be used together with the
      <span class="code">test_server_line</span> parse transform described above. A
      timestamp will then be written for each line in the suite, except
      for functions stated in the <span class="code">-no_lines</span> attribute.
      </p>
    <p>The <span class="code">line_trace</span> macro can e.g. be defined as a compile
      option, like this:
            <br>
<span class="code">erlc -W -Dline_trace my_SUITE.erl</span></p>
  </div>
</div>
<div class="footer">
<hr>
<p>Copyright © 2002-2012 Ericsson AB. All Rights Reserved.</p>
</div>
</div>
</div></body>
</html>