diff options
author | Peter Andersson <[email protected]> | 2011-12-12 03:10:51 +0100 |
---|---|---|
committer | Peter Andersson <[email protected]> | 2011-12-12 05:08:41 +0100 |
commit | e7fc8ebdf5fcf82c581026d7c52e23a53b05ba01 (patch) | |
tree | 6f0a5b5a038b5cc0f7f1fa44b890082431fa6bfb /lib/common_test/doc/src/getting_started_chapter.xml | |
parent | 46ef0536a9e3442c3a54237b59b238e6b6f7a90a (diff) | |
download | otp-e7fc8ebdf5fcf82c581026d7c52e23a53b05ba01.tar.gz otp-e7fc8ebdf5fcf82c581026d7c52e23a53b05ba01.tar.bz2 otp-e7fc8ebdf5fcf82c581026d7c52e23a53b05ba01.zip |
Update basics chapter and introduce getting started chapter
Diffstat (limited to 'lib/common_test/doc/src/getting_started_chapter.xml')
-rw-r--r-- | lib/common_test/doc/src/getting_started_chapter.xml | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/lib/common_test/doc/src/getting_started_chapter.xml b/lib/common_test/doc/src/getting_started_chapter.xml new file mode 100644 index 0000000000..7de0912036 --- /dev/null +++ b/lib/common_test/doc/src/getting_started_chapter.xml @@ -0,0 +1,230 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2007</year><year>2010</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. + + </legalnotice> + + <title>Getting Started</title> + <prepared>Peter Andersson</prepared> + <docno></docno> + <date>2011-12-12</date> + <rev></rev> + <file>getting_started_chapter.xml</file> + </header> + + <section> + <title>Are you new around here?</title> + <p> + The purpose of this short chapter is to, with a "learning by example" + approach, give the newcomer a chance to get started quickly writing and + executing some first simple tests. The chapter will introduce some of the + basics, but leave most explanations and details for the later + chapters in this User's Guide. Hopefully though, after this chapter, you + will be inspired and unintimidated enough to go on and get into the + nitty-gritty that follows in this rather heavy User's Guide! If you're + not much into "learning by example" and prefer to get into more technical + detail right away, go ahead and skip to the next chapter. Again, the basics + presented here will be covered in detail in later chapters. + </p> + <p> + This chapter also tries to demonstrate how dead simple it actually is + to write a very basic (yet for many module testing purposes, often sufficiently + complex) test suite, and execute its test cases. This is not necessarily + obvious when you read the rest of the chapters in the User's Guide. + </p> + <p> + A quick note before we start: In order to understand what's discussed and + examplified here, it is recommended that you first read through the + opening <seealso marker="basics_chapter#basics">Common Test Basics</seealso> + chapter. + </p> + </section> + + <section> + <title>Test case execution</title> + <p>Execution of test cases is handled this way:</p> + + <p> + <image file="tc_execution.gif"> + <icaption> + Successful vs unsuccessful test case execution. + </icaption> + </image> + </p> + + <p>For each test case that Common Test is told to execute, it spawns a + dedicated process on which the test case function in question starts + running. (In parallel to the test case process, an idle waiting timer + process is started which is linked to the test case process. If the timer + process runs out of waiting time, it sends an exit signal to terminate + the test case process and this is what's called a <em>timetrap</em>). + </p> + <p>In scenario 1, the test case process terminates normally after case A has + finished executing its test code without detecting any errors. The test + case function simply returns a value and Common Test logs the test case as + successful. + </p> + <p>In scenario 2, an error is detected during test case execution + which causes the test case B function to generate an exception. + This causes the test case process to exit with reason + other than normal, and as a result, Common Test will log this as an + unsuccessful test case. + </p> + <p>As you can understand from the illustration above, Common Test requires + that a test case generates a runtime error to indicate failure (e.g. + by causing a bad match error or by calling <c>exit/1</c>, preferrably + through the <c>ct:fail/1/2</c> help function). A succesful execution is + indicated by means of a normal return from the test case function. + </p> + </section> + + <section> + <title>A simple test suite</title> + <p>As you've seen in the basics chapter, the test suite module implements + callback functions (mandatory or optional) for various purposes, e.g: + <list> + <item>Init/end configuration function for the test suite</item> + <item>Init/end configuration function for a test case</item> + <item>Init/end configuration function for a test case group</item> + <item>Test cases</item> + </list> + The configuration functions are optional and if you don't need them for + your test, a test suite with one simple test case could look like this: + </p> + <pre> + -module(my1st_SUITE). + -compile(export_all). + + all() -> + [mod_exists]. + + mod_exists(_) -> + {module,mymod} = code:load_file(mymod).</pre> + <p> + In this example we check that the <c>mymod</c> module exists (i.e. can be + successfully loaded by the code server). If the operation fails, we will + get a bad match error which terminates the test case. + </p> + </section> + + <section> + <title>A test suite with configuration functions</title> + <p> + If we need to perform configuration operations in order to run our test, we + implement configuration functions in our suite. The result from a + configuration function is configuration data, or simply <em><c>Config</c></em>. + This is a list of key-value tuples which get passed from the configuration + function to the test cases (possibly through configuration functions on + "lower level"). The data flow looks like this: + </p> + + <p> + <image file="config.gif"> + <icaption> + Config data flow in the suite. + </icaption> + </image> + </p> + + <p> + Here's an example of a test suite which uses configuration functions + to open and close a log file for the test cases (an operation that would + be unnecessary and irrelevant to perform by each test case): + </p> + <pre> + -module(check_log_SUITE). + -export([all/0, init_per_suite/1, end_per_suite/1]). + -export([check_restart_result/1, check_no_errors/1]). + + -define(value(Key,Config), proplists:get_value(Key,Config)). + + all() -> [check_restart_result, check_no_errors]. + + init_per_suite(InitConfigData) -> + [{logref,open_log()} | InitConfigData]. + + end_per_suite(ConfigData) -> + close_log(?value(logref, ConfigData)). + + check_restart_result(ConfigData) -> + TestData = read_log(restart, ?value(logref, ConfigData)), + {match,_Line} = search_for("restart successful", TestData). + + check_no_errors(ConfigData) -> + TestData = read_log(all, ?value(logref, ConfigData)), + case search_for("error", TestData) of + {match,Line} -> ct:fail({error_found_in_log,Line}); + nomatch -> ok + end.</pre> + <p> + In this example we have test cases that verify, by parsing a + log file, that our SUT has performed a successful restart and + that no unexpected errors have been printed. + </p> + + <p>To execute the test cases in the test suite above, we could type this on + the Unix/Linux command line (assuming for this example that the suite module + is in the current working directory): + </p> + <pre> + $ ct_run -dir .</pre> + <p>or</p> + <pre> + $ ct_run -suite check_log_SUITE</pre> + + <p>If we want to use the Erlang shell to run our test, we could evaluate this call: + </p> + <pre> + 1> ct:run_test([{dir, "."}]).</pre> + <p>or</p> + <pre> + 1> ct:run_test([{suite, "check_log_SUITE"}]).</pre> + <p> + The result from running our test is printed in log files on HTML format + (stored in unique log directories on different level). This illustration + shows the log file structure: + </p> + + <p> + <image file="html_logs.gif"> + <icaption> + HTML log file structure. + </icaption> + </image> + </p> + </section> + + <section> + <title>What happens next?</title> + <p> + You will find detailed information about the basics introduced here in this + chapter in the following chapters in the User's Guide, as well as + presentations of many more useful features. Have fun! + </p> + </section> +</chapter> + + + + + + + + |