Files
Roel van Dijk 93b020aef4 Update documentation to 0.9.16 (#10)
Co-authored-by: Roel van Dijk <rdvdijk@users.noreply.github.com>
2026-03-06 09:59:38 +01:00

249 lines
17 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html class="writer-html5" lang="en" data-content_root="../../">
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Advanced use of the Test Framework in Python &mdash; Hansken Extraction Plugins for plugin developers 0.9.16
documentation</title>
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css?v=d75fae25" />
<link rel="stylesheet" type="text/css" href="../../_static/css/theme.css?v=e59714d7" />
<link rel="stylesheet" type="text/css" href="../../_static/wider_pages.css?v=32ad70ab" />
<script src="../../_static/jquery.js?v=5d32c60e"></script>
<script src="../../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
<script src="../../_static/documentation_options.js?v=433a2a34"></script>
<script src="../../_static/doctools.js?v=9a2dae69"></script>
<script src="../../_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="../../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
<link rel="next" title="Run plugins with Hansken.py" href="hanskenpy.html" />
<link rel="prev" title="Using Transformers for on-demand execution" href="transformers.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../../index.html" class="icon icon-home">
Hansken Extraction Plugins for plugin developers
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../introduction.html">Introduction</a></li>
<li class="toctree-l1"><a class="reference internal" href="../concepts.html">General concepts</a></li>
<li class="toctree-l1"><a class="reference internal" href="../spec.html">Extraction Plugin specifications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../java.html">Java</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="../python.html">Python</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="api_changelog.html">Python API Changelog</a></li>
<li class="toctree-l2"><a class="reference internal" href="prerequisites.html">Prerequisites</a></li>
<li class="toctree-l2"><a class="reference internal" href="getting_started.html">Getting started</a></li>
<li class="toctree-l2"><a class="reference internal" href="packaging.html">Packaging</a></li>
<li class="toctree-l2"><a class="reference internal" href="snippets.html">Python code snippets</a></li>
<li class="toctree-l2"><a class="reference internal" href="transformers.html">Using Transformers for on-demand execution</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">Advanced use of the Test Framework in Python</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#regenerate-expected-test-results">Regenerate expected test results</a></li>
<li class="toctree-l3"><a class="reference internal" href="#standalone-testing">Standalone testing</a></li>
<li class="toctree-l3"><a class="reference internal" href="#testing-with-a-docker-image">Testing with a Docker image</a></li>
<li class="toctree-l3"><a class="reference internal" href="#manual-testing">Manual testing</a></li>
<li class="toctree-l3"><a class="reference internal" href="#tip-start-tests-in-your-ide">Tip: Start tests in your IDE</a></li>
<li class="toctree-l3"><a class="reference internal" href="#help">Help</a></li>
<li class="toctree-l3"><a class="reference internal" href="#testing-transformers">Testing transformers</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="hanskenpy.html">Run plugins with Hansken.py</a></li>
<li class="toctree-l2"><a class="reference internal" href="debugging.html">How to debug an Extraction Plugin</a></li>
<li class="toctree-l2"><a class="reference internal" href="../python.html#api-documentation">API Documentation</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../examples.html">Examples</a></li>
<li class="toctree-l1"><a class="reference internal" href="../faq.html">Frequently Asked Questions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../contact.html">Contact</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../changes.html">Changelog</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../../index.html">Hansken Extraction Plugins for plugin developers</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item"><a href="../python.html">Python</a></li>
<li class="breadcrumb-item active">Advanced use of the Test Framework in Python</li>
<li class="wy-breadcrumbs-aside">
<a href="../../_sources/dev/python/testing.md.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="advanced-use-of-the-test-framework-in-python">
<h1>Advanced use of the Test Framework in Python<a class="headerlink" href="#advanced-use-of-the-test-framework-in-python" title="Link to this heading"></a></h1>
<p id="python-testing">This section assumes you use the same setup as is used in
the <a class="reference external" href="https://git.eminjenv.nl/hanskaton/hansken-extraction-plugin-sdk/examples">Extraction Plugin Examples</a>.</p>
<p>By default, the build scripts as described in the <a class="reference internal" href="getting_started.html"><span class="doc">Getting Started</span></a> section will automatically run
tests. The appropriate commands have been added to the tox.ini directly. This section gives a little more detail on the
test commands and options.</p>
<p>One can simply create unit tests for a plugin directly. However, we also provide a test-framework for testing them over
gRPC. The test-framework serves a running instance of a Python plugin, and feeds it input files and compares the results
against an expected result set.</p>
<p>Note that the test-framework is implemented in Java, hence the Java 11 requirement. A jar file is included in the Python
SDK which is called from a Python wrapper.</p>
<section id="regenerate-expected-test-results">
<h2>Regenerate expected test results<a class="headerlink" href="#regenerate-expected-test-results" title="Link to this heading"></a></h2>
<p>The build and test scripts run some integration tests. To update the expected test outcome, the following command can be
used:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>tox<span class="w"> </span>-e<span class="w"> </span>regenerate
</pre></div>
</div>
</section>
<section id="standalone-testing">
<h2>Standalone testing<a class="headerlink" href="#standalone-testing" title="Link to this heading"></a></h2>
<p>The test runner is a script called <code class="docutils literal notranslate"><span class="pre">test_plugin</span></code> which is available in the SDK.</p>
<p>To get started, <code class="docutils literal notranslate"><span class="pre">cd</span></code> into the directory of the plugin you want to test and run:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>test_plugin<span class="w"> </span>--standalone<span class="w"> </span>plugin/chat_plugin.py
</pre></div>
</div>
<p>Note that the argument provided to the option <code class="docutils literal notranslate"><span class="pre">--standalone</span></code> in this example is the relative path to the plugin <code class="docutils literal notranslate"><span class="pre">py</span></code>
file which is to be tested. This test accepts input files from the directory <code class="docutils literal notranslate"><span class="pre">testdata/input</span></code> and compares the results
to the result files in found in <code class="docutils literal notranslate"><span class="pre">testdata/results</span></code>. Use the optional argument <code class="docutils literal notranslate"><span class="pre">--regenerate</span></code> to regenerate the expected
results for the test when needed.</p>
<p>This standalone test is also used by the <code class="docutils literal notranslate"><span class="pre">tox.ini</span></code> file to validate the plugin. Simply calling <code class="docutils literal notranslate"><span class="pre">tox</span></code> should be enough to
install all dependencies and run the test.</p>
<p>In case the plugin was defined in a module that is to be imported by the interpreter, its also possible to run this
command by referencing either the module that defines the plugin or the plugin directly:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>test_plugin<span class="w"> </span>--standalone<span class="w"> </span>plugin_module
<span class="c1"># or, assuming the plugin class is called ChatPlugin</span>
test_plugin<span class="w"> </span>--standalone<span class="w"> </span>plugin_module:ChatPlugin
</pre></div>
</div>
</section>
<section id="testing-with-a-docker-image">
<h2>Testing with a Docker image<a class="headerlink" href="#testing-with-a-docker-image" title="Link to this heading"></a></h2>
<p>If there is a docker image available for the plugin you can also test it by executing:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>test_plugin<span class="w"> </span>--docker<span class="w"> </span>extraction-plugin-examples-my-plugin
</pre></div>
</div>
<p>Replace the extraction-plugin-examples-chat with the docker image you want to test. Run the following command to see
which docker images are available:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>docker<span class="w"> </span>images
</pre></div>
</div>
</section>
<section id="manual-testing">
<h2>Manual testing<a class="headerlink" href="#manual-testing" title="Link to this heading"></a></h2>
<p>The third option for testing is a manually started plugin. Start the plugin service in a terminal by executing:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>serve_plugin<span class="w"> </span>-vvv<span class="w"> </span>plugin/my_plugin.py
</pre></div>
</div>
<p>This will spin up the chat plugin at port 8999. In this example the argument is also a path to the plugins <code class="docutils literal notranslate"><span class="pre">.py</span></code> file.
The same alternative reference to the plugin shown with <code class="docutils literal notranslate"><span class="pre">test_plugin</span></code> above applies here.</p>
<p>In another terminal window, run the test with:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>test_plugin<span class="w"> </span>--manual<span class="w"> </span>localhost<span class="w"> </span><span class="m">8999</span>
</pre></div>
</div>
</section>
<section id="tip-start-tests-in-your-ide">
<h2>Tip: Start tests in your IDE<a class="headerlink" href="#tip-start-tests-in-your-ide" title="Link to this heading"></a></h2>
<p>To start the extraction plugin from code, create a <code class="docutils literal notranslate"><span class="pre">__main__</span></code> method which calls the <code class="docutils literal notranslate"><span class="pre">_test_validate_standalone</span></code>
method of the test framework (see the example below). This method causes the extraction plugin to be started and
supplied with data by the FLITS test framework. In this way the test can be started from the IDE, which has the
advantage that it is easier to debug.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">hansken_extraction_plugin.test_framework.test_plugin</span><span class="w"> </span><span class="kn">import</span> <span class="n">_test_validate_standalone</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">hansken_extraction_plugin.api.extraction_plugin</span><span class="w"> </span><span class="kn">import</span> <span class="n">ExtractionPlugin</span>
<span class="k">class</span><span class="w"> </span><span class="nc">PluginToTest</span><span class="p">(</span><span class="n">ExtractionPlugin</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="nf">plugin_info</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1"># return plugin info</span>
<span class="k">pass</span>
<span class="k">def</span><span class="w"> </span><span class="nf">process</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">trace</span><span class="p">,</span> <span class="n">data_context</span><span class="p">):</span>
<span class="c1"># process the data/trace here</span>
<span class="k">pass</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
<span class="n">_test_validate_standalone</span><span class="p">(</span><span class="n">PluginToTest</span><span class="p">,</span> <span class="s1">&#39;testdata/input&#39;</span><span class="p">,</span> <span class="s1">&#39;testdata/result&#39;</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="help">
<h2>Help<a class="headerlink" href="#help" title="Link to this heading"></a></h2>
<p>Run the following for an overview of all the available options in the test script:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>test_plugin<span class="w"> </span>--help
</pre></div>
</div>
</section>
<section id="testing-transformers">
<h2>Testing transformers<a class="headerlink" href="#testing-transformers" title="Link to this heading"></a></h2>
<p>The sdk includes a script to test transformer functions. This script will start an extraction plugin, executes a single transformer function with the provided arguments and stops the plugin. Try it with:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>execute_transformer<span class="w"> </span>docker_image<span class="w"> </span>method_name<span class="w"> </span>arguments
</pre></div>
</div>
<p>The arguments are provided in named argument pairs, so calling a method called <code class="docutils literal notranslate"><span class="pre">translate</span></code> with two parameters <code class="docutils literal notranslate"><span class="pre">language</span></code> and <code class="docutils literal notranslate"><span class="pre">input</span></code> might look like this:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>execute_transformer<span class="w"> </span>translator_plugin<span class="w"> </span>translate<span class="w"> </span>language<span class="w"> </span>nl_NL<span class="w"> </span>input<span class="w"> </span><span class="s2">&quot;example input&quot;</span>
</pre></div>
</div>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="transformers.html" class="btn btn-neutral float-left" title="Using Transformers for on-demand execution" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="hanskenpy.html" class="btn btn-neutral float-right" title="Run plugins with Hansken.py" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2020-2026 Netherlands Forensic Institute.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>