aboutsummaryrefslogtreecommitdiffstats
path: root/lib/test_server/doc/src/test_server.xml
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/test_server/doc/src/test_server.xml
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/test_server/doc/src/test_server.xml')
-rw-r--r--lib/test_server/doc/src/test_server.xml840
1 files changed, 840 insertions, 0 deletions
diff --git a/lib/test_server/doc/src/test_server.xml b/lib/test_server/doc/src/test_server.xml
new file mode 100644
index 0000000000..6e75425862
--- /dev/null
+++ b/lib/test_server/doc/src/test_server.xml
@@ -0,0 +1,840 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Ericsson AB, All Rights Reserved</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+ </legalnotice>
+
+ <title>test_server</title>
+ <prepared>Siri Hansen</prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev></rev>
+ <file>test_server_ref.sgml</file>
+ </header>
+ <module>test_server</module>
+ <modulesummary>This module provides support for test suite authors.</modulesummary>
+ <description>
+ <p>The <c>test_server</c> module aids the test suite author by providing
+ various support functions. The supported functionality includes:
+ </p>
+ <list type="bulleted">
+ <item>Logging and timestamping
+ </item>
+ <item>Capturing output to stdout
+ </item>
+ <item>Retrieving and flushing the message queue of a process
+ </item>
+ <item>Watchdog timers, process sleep, time measurement and unit
+ conversion
+ </item>
+ <item>Private scratch directory for all test suites
+ </item>
+ <item>Start and stop of slave- or peer nodes</item>
+ </list>
+ <p>For more information on how to write test cases and for
+ examples, please see the Test Server User's Guide.
+ </p>
+ </description>
+
+ <section>
+ <title>TEST SUITE SUPPORT FUNCTIONS</title>
+ <p>The following functions are supposed to be used inside a test
+ suite.
+ </p>
+ </section>
+ <funcs>
+ <func>
+ <name>os_type() -> OSType</name>
+ <fsummary>Returns the OS type of the target node</fsummary>
+ <type>
+ <v>OSType = term()</v>
+ <d>This is the same as returned from <c>os:type/0</c></d>
+ </type>
+ <desc>
+ <p>This function can be called on controller or target node, and
+ it will always return the OS type of the target node.</p>
+ </desc>
+ </func>
+ <func>
+ <name>fail()</name>
+ <name>fail(Reason)</name>
+ <fsummary>Makes the test case fail.</fsummary>
+ <type>
+ <v>Reason = term()</v>
+ <d>The reason why the test case failed.</d>
+ </type>
+ <desc>
+ <p>This will make the test suite fail with a given reason, or
+ with <c>suite_failed</c> 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. <c>Reason</c>
+ will appear in the comment field in the HTML log.</p>
+ </desc>
+ </func>
+ <func>
+ <name>timetrap(Timout) -> Handle</name>
+ <fsummary></fsummary>
+ <type>
+ <v>Timeout = integer() | {hours,H} | {minutes,M} | {seconds,S}</v>
+ <v>H = M = S = integer()</v>
+ <v>Pid = pid()</v>
+ <d>The process that is to be timetrapped (<c>self()</c>by default)</d>
+ </type>
+ <desc>
+ <p>Sets up a time trap for the current process. An expired
+ timetrap kills the process with reason
+ <c>timetrap_timeout</c>. The returned handle is to be given
+ as argument to <c>timetrap_cancel</c> before the timetrap
+ expires. If <c>Timeout</c> is an integer, it is expected to
+ be milliseconds.</p>
+ <note>
+ <p>If the current process is trapping exits, it will not be killed
+ by the exit signal with reason <c>timetrap_timeout</c>.
+ If this happens, the process will be sent an exit signal
+ with reason <c>kill</c> 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>
+ </note>
+ </desc>
+ </func>
+ <func>
+ <name>timetrap_cancel(Handle) -> ok</name>
+ <fsummary>Cancels a timetrap.</fsummary>
+ <type>
+ <v>Handle = term()</v>
+ <d>Handle returned from <c>timetrap</c></d>
+ </type>
+ <desc>
+ <p>This function cancels a timetrap. This must be done before
+ the timetrap expires.</p>
+ </desc>
+ </func>
+ <func>
+ <name>timetrap_scale_factor() -> ScaleFactor</name>
+ <fsummary>Returns the scale factor for timeouts.</fsummary>
+ <type>
+ <v>ScaleFactor = integer()</v>
+ </type>
+ <desc>
+ <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 <c>cover</c>, 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>
+ </desc>
+ </func>
+ <func>
+ <name>sleep(MSecs) -> ok</name>
+ <fsummary>Suspens the calling task for a specified time.</fsummary>
+ <type>
+ <v>MSecs = integer() | float() | infinity</v>
+ <d>The number of milliseconds to sleep</d>
+ </type>
+ <desc>
+ <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
+ <c>timer:sleep</c>, the first being that the module
+ <c>timer</c> may be unavailable at the time the test suite is
+ run, and the second that it also accepts floating point
+ numbers.</p>
+ </desc>
+ </func>
+ <func>
+ <name>hours(N) -> MSecs</name>
+ <name>minutes(N) -> MSecs</name>
+ <name>seconds(N) -> MSecs</name>
+ <fsummary></fsummary>
+ <type>
+ <v>N = integer()</v>
+ <d>Value to convert to milliseconds.</d>
+ </type>
+ <desc>
+ <p>Theese functions convert <c>N</c> number of hours, minutes
+ or seconds into milliseconds.
+ </p>
+ <p>Use this function when you want to
+ <c>test_server:sleep/1</c> for a number of seconds, minutes or
+ hours(!).</p>
+ </desc>
+ </func>
+ <func>
+ <name>format(Format) -> ok</name>
+ <name>format(Format, Args)</name>
+ <name>format(Pri,Format)</name>
+ <name>format(Pri, Format, Args)</name>
+ <fsummary></fsummary>
+ <type>
+ <v>Format = string()</v>
+ <d>Format as described for <c>io_:format</c>.</d>
+ <v>Args = list()</v>
+ <d>List of arguments to format.</d>
+ </type>
+ <desc>
+ <p>Formats output just like <c>io:format</c> but sends the
+ formatted string to a logfile. If the urgency value,
+ <c>Pri</c>, 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 <c>test_server_ctrl:set_levels/3</c>
+ function.</p>
+ </desc>
+ </func>
+ <func>
+ <name>capture_start() -> ok</name>
+ <name>capture_stop() -> ok</name>
+ <name>capture_get() -> list()</name>
+ <fsummary>Captures all output to stdout for a process.</fsummary>
+ <desc>
+ <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 <c>capture_get</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>messages_get() -> list()</name>
+ <fsummary>Empty the message queue.</fsummary>
+ <desc>
+ <p>This function will empty and return all the messages
+ currently in the calling process' message queue.</p>
+ </desc>
+ </func>
+ <func>
+ <name>timecall(M, F, A) -> {Time, Value}</name>
+ <fsummary>Measures the time needed to call a function.</fsummary>
+ <type>
+ <v>M = atom()</v>
+ <d>The name of the module where the function resides.</d>
+ <v>F = atom()</v>
+ <d>The name of the function to call in the module.</d>
+ <v>A = list()</v>
+ <d>The arguments to supply the called function.</d>
+ <v>Time = integer()</v>
+ <d>The number of seconds it took to call the function.</d>
+ <v>Value = term()</v>
+ <d>Value returned from the called function.</d>
+ </type>
+ <desc>
+ <p>This function measures the time (in seconds) it takes to
+ call a certain function. The function call is <em>not</em>
+ caught within a catch.</p>
+ </desc>
+ </func>
+ <func>
+ <name>do_times(N, M, F, A) -> ok</name>
+ <name>do_times(N, Fun)</name>
+ <fsummary>Calls MFA or Fun N times.</fsummary>
+ <type>
+ <v>N = integer()</v>
+ <d>Number of times to call MFA.</d>
+ <v>M = atom()</v>
+ <d>Module name where the function resides.</d>
+ <v>F = atom()</v>
+ <d>Function name to call.</d>
+ <v>A = list()</v>
+ <d>Arguments to M:F.</d>
+ </type>
+ <desc>
+ <p>Calls MFA or Fun N times. Useful for extensive testing of a
+ sensitive function.</p>
+ </desc>
+ </func>
+ <func>
+ <name>m_out_of_n(M, N, Fun) -> ok | exit({m_out_of_n_failed, {R,left_to_do}}</name>
+ <fsummary>Fault tolerant <c>do_times</c>.</fsummary>
+ <type>
+ <v>N = integer()</v>
+ <d>Number of times to call the Fun.</d>
+ <v>M = integer()</v>
+ <d>Number of times to require a successful return.</d>
+ </type>
+ <desc>
+ <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><c>m_out_of_n(1,4,fun() -> tricky_test_case() end)</c> <br></br>
+Tries to run tricky_test_case() up to 4 times, and is
+ happy if it succeeds once.
+ </p>
+ <p><c>m_out_of_n(7,8,fun() -> clock_sanity_check() end)</c> <br></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>
+ </desc>
+ </func>
+ <func>
+ <name>call_crash(M, F, A) -> Result</name>
+ <name>call_crash(Time, M, F, A) -> Result</name>
+ <name>call_crash(Time, Crash, M, F, A) -> Result</name>
+ <fsummary>Calls MFA and succeeds if it crashes.</fsummary>
+ <type>
+ <v>Result = ok | exit(call_crash_timeout) | exit({wrong_crash_reason, Reason})</v>
+ <v>Crash = term()</v>
+ <d>Crash return from the function.</d>
+ <v>Time = integer()</v>
+ <d>Timeout in milliseconds.</d>
+ <v>M = atom()</v>
+ <d>Module name where the function resides.</d>
+ <v>F = atom()</v>
+ <d>Function name to call.</d>
+ <v>A = list()</v>
+ <d>Arguments to M:F.</d>
+ </type>
+ <desc>
+ <p>Spawns a new process that calls MFA. The call is considered
+ successful if the call crashes with the gives reason
+ (<c>Crash</c>) or any reason if not specified. The call must
+ terminate within the given time (default <c>infinity</c>), or
+ it is considered a failure.</p>
+ </desc>
+ </func>
+ <func>
+ <name>temp_name(Stem) -> Name</name>
+ <fsummary>Returns a unique filename.</fsummary>
+ <type>
+ <v>Stem = string()</v>
+ </type>
+ <desc>
+ <p>Returns a unique filename starting with <c>Stem</c> 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>
+ </desc>
+ </func>
+ <func>
+ <name>break(Comment) -> ok</name>
+ <fsummary>Cancel all timetraps and wait for call to continue/0.</fsummary>
+ <type>
+ <v>Comment = string()</v>
+ </type>
+ <desc>
+ <p><c>Comment</c> 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
+ <c>continue/0</c> 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 <c>break/1</c> function is called, the shell will
+ look something like this:</p>
+ <code type="none"><![CDATA[
+ --- SEMIAUTOMATIC TESTING ---
+ The test case executes on process <0.51.0>
+
+
+ "Here is a comment, it could e.g. instruct to pull out a card"
+
+
+ -----------------------------
+
+ Continue with --> test_server:continue(). ]]></code>
+ <p>The user can now interact with the erlang node, and when
+ ready call <c>test_server:continue().</c></p>
+ <p>Note that this function can not be used if the test is
+ executed with <c>ts:run/0/1/2/3/4</c> in <c>batch</c> mode.</p>
+ </desc>
+ </func>
+ <func>
+ <name>continue() -> ok</name>
+ <fsummary>Continue after break/1.</fsummary>
+ <desc>
+ <p>This function must be called in order to continue after a
+ test case has called <c>break/1</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>run_on_shielded_node(Fun, CArgs) -> term()</name>
+ <fsummary>Execute a function a shielded node.</fsummary>
+ <type>
+ <v>Fun = function() (arity 0)</v>
+ <d>Function to execute on the shielded node.</d>
+ <v>CArg = string()</v>
+ <d>Extra command line arguments to use when starting the shielded node.</d>
+ </type>
+ <desc>
+ <p><c>Fun</c> 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 <c>Fun</c> is successfully executed, the result
+ is returned. A peer node (see <c>start_node/3</c>) 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 <c>+R</c> flag in the <c>erl(1)</c> 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>
+ <note>
+ <p>You <em>must</em> make sure that nodes started by the shielded
+ node never communicate directly with the test server node.</p>
+ </note>
+ <note>
+ <p>Slave nodes always communicate with the test server node;
+ therefore, <em>never</em> start <em>slave nodes</em> from the
+ shielded node, <em>always</em> start <em>peer nodes</em>.</p>
+ </note>
+ </desc>
+ </func>
+ <func>
+ <name>start_node(Name, Type, Options) -> {ok, Node} | {error, Reason}</name>
+ <fsummary>Start a node.</fsummary>
+ <type>
+ <v>Name = atom() | string()</v>
+ <d>Name of the slavenode to start (as given to -sname or -name)</d>
+ <v>Type = slave | peer</v>
+ <d>The type of node to start.</d>
+ <v>Options = [{atom(), term()]</v>
+ <d>Tuplelist of options</d>
+ </type>
+ <desc>
+ <p>This functions starts a node, possibly on a remote machine,
+ and guarantees cross architecture transparency. Type is set to
+ either <c>slave</c> or <c>peer</c>.
+ </p>
+ <p><c>slave</c> 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><c>peer</c> means that the new node is an independent node
+ with no master.
+ </p>
+ <p><c>Options</c> is a tuplelist which can contain one or more
+ of
+ </p>
+ <taglist>
+ <tag><c>{remote, true}</c></tag>
+ <item>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.
+ </item>
+ <tag><c>{args, Arguments}</c></tag>
+ <item>Arguments passed directly to the node. This is
+ typically a string appended to the command line.
+ </item>
+ <tag><c>{wait, false}</c></tag>
+ <item>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></br>
+Only valid for peer nodes
+ </item>
+ <tag><c>{fail_on_error, false}</c></tag>
+ <item>Returns <c>{error, Reason}</c> rather than failing the
+ test case.
+ <br></br>
+Only valid for peer nodes. Note that slave nodes always
+ act as if they had <c>fail_on_error=false</c></item>
+ <tag><c>{erl, ReleaseList}</c></tag>
+ <item>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>
+ <br></br>
+
+ When specifying this option to run a previous release, use
+ <c>is_release_available/1</c> function to test if the given
+ release is available and skip the test case if not.
+ <br></br>
+ <br></br>
+
+ In order to avoid compatibility problems (may not appear right
+ away), use a shielded node (see <c>run_on_shielded_node/2</c>)
+ when starting nodes from different OTP releases than the test
+ server.
+ </item>
+ <tag><c>{cleanup, false}</c></tag>
+ <item>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.
+ </item>
+ <tag><c>{env, Env}</c></tag>
+ <item><c>Env</c> should be a list of tuples <c>{Name, Val}</c>,
+ where <c>Name</c> is the name of an environment variable, and
+ <c>Val</c> is the value it is to have in the started node.
+ Both <c>Name</c> and <c>Val</c> must be strings. The one
+ exception is <c>Val</c> being the atom <c>false</c> (in
+ analogy with <c>os:getenv/1</c>), which removes the
+ environment variable. Only valid for peer nodes. Not
+ available on VxWorks.</item>
+ </taglist>
+ </desc>
+ </func>
+ <func>
+ <name>stop_node(NodeName) -> bool()</name>
+ <fsummary>Stops a node</fsummary>
+ <type>
+ <v>NodeName = term()</v>
+ <d>Name of the node to stop</d>
+ </type>
+ <desc>
+ <p>This functions stops a node previously started with
+ <c>start_node/3</c>. 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 <c>{cleanup, false}</c> option.</p>
+ </desc>
+ </func>
+ <func>
+ <name>is_commercial() -> bool()</name>
+ <fsummary>Tests whether the emulator is commercially supported</fsummary>
+ <desc>
+ <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>
+ </desc>
+ </func>
+
+ <func>
+ <name>is_release_available(Release) -> bool()</name>
+ <fsummary>Tests whether a release is available</fsummary>
+ <type>
+ <v>Release = string() | atom()</v>
+ <d>Release to test for</d>
+ </type>
+ <desc>
+ <p>This function test whether the release given by
+ <c>Release</c> (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 <c>suite</c>
+ clause of a test case, as the test_server will deadlock.</p>
+ </desc>
+ </func>
+ <func>
+ <name>is_native(Mod) -> bool()</name>
+ <fsummary>Checks whether the module is natively compiled or not</fsummary>
+ <type>
+ <v>Mod = atom()</v>
+ <d>A module name</d>
+ </type>
+ <desc>
+ <p>Checks whether the module is natively compiled or not</p>
+ </desc>
+ </func>
+ <func>
+ <name>app_test(App) -> ok | test_server:fail()</name>
+ <name>app_test(App,Mode)</name>
+ <fsummary>Checks an applications .app file for obvious errors</fsummary>
+ <type>
+ <v>App = term()</v>
+ <d>The name of the application to test</d>
+ <v>Mode = pedantic | tolerant</v>
+ <d>Default is pedantic</d>
+ </type>
+ <desc>
+ <p>Checks an applications .app file for obvious errors.
+ The following is checked:
+ </p>
+ <list type="bulleted">
+ <item>required fields
+ </item>
+ <item>that all modules specified actually exists
+ </item>
+ <item>that all requires applications exists
+ </item>
+ <item>that no module included in the application has export_all
+ </item>
+ <item>that all modules in the ebin/ dir is included (If
+ <c>Mode==tolerant</c> this only produces a warning, as all
+ modules does not have to be included)</item>
+ </list>
+ </desc>
+ </func>
+ <func>
+ <name>comment(Comment) -> ok</name>
+ <fsummary>Print a comment on the HTML result page</fsummary>
+ <type>
+ <v>Comment = string()</v>
+ </type>
+ <desc>
+ <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>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <title>TEST SUITE EXPORTS</title>
+ <p>The following functions must be exported from a test suite
+ module.
+ </p>
+ </section>
+ <funcs>
+ <func>
+ <name>all(suite) -> TestSpec | {skip, Comment}</name>
+ <fsummary>Returns the module's test specification</fsummary>
+ <type>
+ <v>TestSpec = list()</v>
+ <v>Comment = string()</v>
+ <d>This comment will be printed on the HTML result page</d>
+ </type>
+ <desc>
+ <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>
+ </desc>
+ </func>
+ <func>
+ <name>init_per_suite(Config0) -> Config1 | {skip, Comment}</name>
+ <fsummary>Test suite initiation</fsummary>
+ <type>
+ <v>Config0 = Config1 = [tuple()]</v>
+ <v>Comment = string()</v>
+ <d>Describes why the suite is skipped</d>
+ </type>
+ <desc>
+ <p>This function is called before all other test cases in the
+ suite. <c>Config</c> is the configuration which can be modified
+ here. Whatever is returned from this function is given as
+ <c>Config</c> to the test cases.
+ </p>
+ <p>If this function fails, all test cases in the suite will be
+ skipped.</p>
+ </desc>
+ </func>
+ <func>
+ <name>end_per_suite(Config) -> void()</name>
+ <fsummary>Test suite finalization</fsummary>
+ <type>
+ <v>Config = [tuple()]</v>
+ </type>
+ <desc>
+ <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>
+ </desc>
+ </func>
+ <func>
+ <name>init_per_testcase(Case, Config0) -> Config1 | {skip, Comment}</name>
+ <fsummary>Test case initiation</fsummary>
+ <type>
+ <v>Case = atom()</v>
+ <v>Config0 = Config1 = [tuple()]</v>
+ <v>Comment = string()</v>
+ <d>Describes why the test case is skipped</d>
+ </type>
+ <desc>
+ <p>This function is called before each test case. The
+ <c>Case</c> argument is the name of the test case, and
+ <c>Config</c> is the configuration which can be modified
+ here. Whatever is returned from this function is given as
+ <c>Config</c> to the test case.</p>
+ </desc>
+ </func>
+ <func>
+ <name>end_per_testcase(Case, Config) -> void()</name>
+ <fsummary>Test case finalization</fsummary>
+ <type>
+ <v>Case = atom()</v>
+ <v>Config = [tuple()]</v>
+ </type>
+ <desc>
+ <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>
+ </desc>
+ </func>
+ <func>
+ <name>Case(doc) -> [Decription]</name>
+ <name>Case(suite) -> [] | TestSpec | {skip, Comment}</name>
+ <name>Case(Config) -> {skip, Comment} | {comment, Comment} | Ok</name>
+ <fsummary>A test case</fsummary>
+ <type>
+ <v>Description = string()</v>
+ <d>Short description of the test case</d>
+ <v>TestSpec = list()</v>
+ <v>Comment = string()</v>
+ <d>This comment will be printed on the HTML result page</d>
+ <v>Ok = term()</v>
+ <v>Config = [tuple()]</v>
+ <d>Elements from the Config parameter can be read with the ?config macro, see section about test suite support macros</d>
+ </type>
+ <desc>
+ <p>The <em>documentation clause</em> (argument <c>doc</c>) can
+ be used for automatic generation of test documentation or test
+ descriptions.
+ </p>
+ <p>The <em>specification clause</em> (argument <c>spec</c>)
+ shall return an empty list, the test specification for the
+ test case or <c>{skip,Comment}</c>. The syntax of a test
+ specification is described in the Test Server User's Guide.
+ </p>
+ <p><em>Note that the specification clause always is executed on the controller host.</em></p>
+ <p>The <em>execution clause</em> (argument <c>Config</c>) 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 <c>test_server:fail/0/1</c> (which also will
+ cause the process to crash).
+ </p>
+ <p>You can return <c>{skip,Comment}</c> 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 <c>{comment,Comment}</c> 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 <c>{'EXIT',Reason}</c> or
+ <c>{'EXIT',Pid,Reason}</c> which can't be distinguished from a
+ crash, and thus will be considered a failure.
+ </p>
+ <p>A <em>conf test case</em> 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>
+ <list type="bulleted">
+ <item>They do not need a specification clause.</item>
+ <item>They must always have the execution clause.</item>
+ <item>They must return the <c>Config</c> parameter, a modified
+ version of it or <c>{skip,Comment}</c> from the execution clause.</item>
+ <item>The cleanup function may also return a tuple
+ <c>{return_group_result,Status}</c>, which is used to return the
+ status of the conf case to Test Server and/or to a conf case on a
+ higher level. (<c>Status = ok | skipped | failed</c>).</item>
+ <item><c>init_per_testcase</c> and <c>end_per_testcase</c> are
+ not called before and after these functions.</item>
+ </list>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <title>TEST SUITE LINE NUMBERS</title>
+ <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 <c>line</c> macro or by using the
+ <c>test_server_line</c> parse transform.
+ </p>
+ <p>The <c>line</c> macro is described under TEST SUITE SUPPORT
+ MACROS below. The <c>line</c> macro will only report the last line
+ executed when a test case failed.
+ </p>
+ <p>The <c>test_server_line</c> parse transform is activated by
+ including the headerfile <c>test_server_line.hrl</c> in the test
+ suite. When doing this, it is important that the
+ <c>test_server_line</c> 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 <c>-no_lines(FuncList).</c> 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. <c>FuncList = [{Func,Arity}]</c>.
+ </p>
+ <p>If both the <c>line</c> macro and the parse transform is used in
+ the same module, the parse transform will overrule the macro.
+ </p>
+ </section>
+
+ <section>
+ <title>TEST SUITE SUPPORT MACROS</title>
+ <p>There are some macros defined in the <c>test_server.hrl</c>
+ that are quite useful for test suite programmers:
+ </p>
+ <p>The <em>line</em> 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 <em>config</em> macro, is used to
+ retrieve information from the <c>Config</c> 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 <c>Config</c> variable supplied to the test case
+ from the test server.
+ </p>
+ <p>Possible configuration variables include:</p>
+ <list type="bulleted">
+ <item><c>data_dir</c> - Data file directory.</item>
+ <item><c>priv_dir</c> - Scratch file directory.</item>
+ <item><c>nodes</c> - Nodes specified in the spec file</item>
+ <item><c>nodenames</c> - Generated nodenames.</item>
+ <item>Whatever added by conf test cases or
+ <c>init_per_testcase/2</c></item>
+ </list>
+ <p>Examples of the <c>line</c> and <c>config</c> macros can be
+ seen in the Examples chapter in the user's guide.
+ </p>
+ <p>If the <c>line_trace</c> macro is defined, you will get a
+ timestamp (<c>erlang:now()</c>) in your minor log for each
+ <c>line</c> 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 <c>line_trace</c> macro can also be used together with the
+ <c>test_server_line</c> parse transform described above. A
+ timestamp will then be written for each line in the suite, except
+ for functions stated in the <c>-no_lines</c> attribute.
+ </p>
+ <p>The <c>line_trace</c> macro can e.g. be defined as a compile
+ option, like this:
+ <br></br>
+<c>erlc -W -Dline_trace my_SUITE.erl</c></p>
+ </section>
+</erlref>
+