<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/18663">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">doc: manual: Write initial Test API section<br><br>Change-Id: I86bc9a8a0b5ff50e72c21a4bd8a857830bd84c4c<br>---<br>M doc/manuals/chapters/test_api.adoc<br>1 file changed, 105 insertions(+), 2 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-gsm-tester refs/changes/63/18663/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/doc/manuals/chapters/test_api.adoc b/doc/manuals/chapters/test_api.adoc</span><br><span>index f541231..f159348 100644</span><br><span>--- a/doc/manuals/chapters/test_api.adoc</span><br><span>+++ b/doc/manuals/chapters/test_api.adoc</span><br><span>@@ -1,4 +1,107 @@</span><br><span> == Test API</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-*TODO* (in the meantime, look at src/osmo_gsm_tester/test.py, as well as</span><br><span style="color: hsl(0, 100%, 40%);">-suite.py, which calls the test's setup() function to get an idea)</span><br><span style="color: hsl(120, 100%, 40%);">+All tests run by {app-name} are python script files. On top of usual python</span><br><span style="color: hsl(120, 100%, 40%);">+standard features, {app-name} provides a set of public APIs and tools that</span><br><span style="color: hsl(120, 100%, 40%);">+these tests can use in order to interact with the core of {app-name}, like</span><br><span style="color: hsl(120, 100%, 40%);">+creating object classes, run processes synchronously or asynchronously, wait for</span><br><span style="color: hsl(120, 100%, 40%);">+events, retrieve specific configuration, etc. This section aims at documenting</span><br><span style="color: hsl(120, 100%, 40%);">+the most relevant tools available for tests.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+First of all, it is important to avoid blocking out of the core's main event loop in</span><br><span style="color: hsl(120, 100%, 40%);">+the test, since doing that will prevent {app-name} core functionalities to work</span><br><span style="color: hsl(120, 100%, 40%);">+properly, such as control of asynchronous processes.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+To get access to those functionalities, a test must import a test environment</span><br><span style="color: hsl(120, 100%, 40%);">+previously prepared by {app-name} before the test was started:</span><br><span style="color: hsl(120, 100%, 40%);">+[source,python]</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/env python3</span><br><span style="color: hsl(120, 100%, 40%);">+from osmo_gsm_tester.testenv import *</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+After the test environment is imported, aome usual functionalities are available</span><br><span style="color: hsl(120, 100%, 40%);">+directly under the global scope. Specially noticeable is the existence of object</span><br><span style="color: hsl(120, 100%, 40%);">+_tenv_, which provides access to most of the functionalities.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The test can simply ask {app-name} to sleep some time, while giving control back</span><br><span style="color: hsl(120, 100%, 40%);">+to {app-name} core's mainloop:</span><br><span style="color: hsl(120, 100%, 40%);">+[source,python]</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+sleep(3) # sleep for 3 seconds</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+One can also wait for events in the background, for instance launch a child</span><br><span style="color: hsl(120, 100%, 40%);">+process locally in the same host and wait for its termination:</span><br><span style="color: hsl(120, 100%, 40%);">+[source,python]</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+proc = process.Process('process_description_name', working_dir_to_store_logs, 'sleep 4') <1></span><br><span style="color: hsl(120, 100%, 40%);">+tenv.remember_to_stop(proc) <2></span><br><span style="color: hsl(120, 100%, 40%);">+proc.launch() <3></span><br><span style="color: hsl(120, 100%, 40%);">+proc.wait() <4></span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+<1> Create process object. This line doesn't yet runs it.</span><br><span style="color: hsl(120, 100%, 40%);">+<2> Make sure the core will kill the process if this test fails</span><br><span style="color: hsl(120, 100%, 40%);">+<3> Start process asynchronously</span><br><span style="color: hsl(120, 100%, 40%);">+<4> wait until process is done. One could waiting generically here too: _wait(proc.terminated)_</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+If running asynchronously is not needed, one can run synchronously in an easy</span><br><span style="color: hsl(120, 100%, 40%);">+way:</span><br><span style="color: hsl(120, 100%, 40%);">+[source,python]</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+proc = process.Process('process_description_name', working_dir_to_store_logs, 'sleep 4')</span><br><span style="color: hsl(120, 100%, 40%);">+proc.launch_sync()</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+One can also log output using either the regular _print_ function from python,</span><br><span style="color: hsl(120, 100%, 40%);">+or using {app-name} specific functions available:</span><br><span style="color: hsl(120, 100%, 40%);">+[source,python]</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+log('this is a regular log message')</span><br><span style="color: hsl(120, 100%, 40%);">+dbg('this is a dbg message, only printed on outputs where dbg is enabled')</span><br><span style="color: hsl(120, 100%, 40%);">+err('outputs log message for non-expected events')</span><br><span style="color: hsl(120, 100%, 40%);">+print('this is the same as log()')</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The test also gains access to suite and/or test specific configuration through</span><br><span style="color: hsl(120, 100%, 40%);">+different APIs:</span><br><span style="color: hsl(120, 100%, 40%);">+[source,python]</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+test_config = tenv.config_test_specific()</span><br><span style="color: hsl(120, 100%, 40%);">+threshold = int(test_config.get('threshold', 2))</span><br><span style="color: hsl(120, 100%, 40%);">+suite_config = tenv.config_suite_specific()</span><br><span style="color: hsl(120, 100%, 40%);">+foobar = suite_config['foobar']</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+A test requiring a really specific config file for an object class it is going</span><br><span style="color: hsl(120, 100%, 40%);">+to run can provide its own template files by overlaying an own directory</span><br><span style="color: hsl(120, 100%, 40%);">+containing them on top of the usual default directory where object class</span><br><span style="color: hsl(120, 100%, 40%);">+templates are (_osmo-gsm-tester.git/src/osmo_gsm_tester/obj/templates/_):</span><br><span style="color: hsl(120, 100%, 40%);">+[source,python]</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+tenv.set_overlay_template_dir(os.path.join(os.path.dirname(__file__), 'mytemplatedir'))</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Several tests in a suite can also share code by using some APIs provided by</span><br><span style="color: hsl(120, 100%, 40%);">+{app-names}. The shared python code must be placed in files under the 'lib/'</span><br><span style="color: hsl(120, 100%, 40%);">+subdirectory in the suite directory where the test belongs to.</span><br><span style="color: hsl(120, 100%, 40%);">+[source,python]</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+# File containing function foobar() available under ${suite_dir}/lib/testlib.py:</span><br><span style="color: hsl(120, 100%, 40%);">+import testlib</span><br><span style="color: hsl(120, 100%, 40%);">+tenv.test_import_modules_register_for_cleanup(testlib)</span><br><span style="color: hsl(120, 100%, 40%);">+from testlib import foobar</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+For a complete set of features and how to use them, one can have a look at real</span><br><span style="color: hsl(120, 100%, 40%);">+examples present in {app-name} git repository under the _sysmocom/_ directory.</span><br><span style="color: hsl(120, 100%, 40%);">+Besides those, have a look too a _testenv.py_ file, which implements the 'tenv'</span><br><span style="color: hsl(120, 100%, 40%);">+object available to tests.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+=== Test verdict</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+In general, a test reaching the end of the file and returning control to</span><br><span style="color: hsl(120, 100%, 40%);">+{app-name} core will be flagged as a successful test (PASS).</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+If an exception is thrown from within the test file and propagated to</span><br><span style="color: hsl(120, 100%, 40%);">+{app-name}, the test will be considered as failed and {app-name} will store all</span><br><span style="color: hsl(120, 100%, 40%);">+failure related information from the caught exception.</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/18663">change 18663</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/18663"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-gsm-tester </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I86bc9a8a0b5ff50e72c21a4bd8a857830bd84c4c </div>
<div style="display:none"> Gerrit-Change-Number: 18663 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>