{"id":197952,"date":"2026-02-17T09:06:42","date_gmt":"2026-02-17T09:06:42","guid":{"rendered":"https:\/\/innovationspace.ansys.com\/knowledge\/?post_type=topic&#038;p=197952"},"modified":"2026-02-27T09:30:37","modified_gmt":"2026-02-27T09:30:37","slug":"testing-scade-one-models-with-python","status":"publish","type":"topic","link":"https:\/\/innovationspace.ansys.com\/knowledge\/forums\/topic\/testing-scade-one-models-with-python\/","title":{"rendered":"Testing Scade One models with Python"},"content":{"rendered":"<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2026\/02\/scade-058-banner-scaled.jpeg\" style=\"max-height: 700px !important\" \/><br \/>\n    <em><\/em>\n<\/p>\n<p>Model-based development is evolving quickly, and <strong>Scade One <\/strong>represents the next generation of SCADE technology, designed to make embedded software modeling more intuitive, scalable, and accessible. While Scade One possesses a fully-integrated, <a href=\"https:\/\/innovationspace.ansys.com\/knowledge\/forums\/topic\/test-harness-a-new-approach-to-testing-in-scade-one\/\">model-based test offer<\/a>, it is also open to interfacing with other testing frameworks as required by user workflows. In particular, the <a href=\"https:\/\/scadeone.docs.pyansys.com\/\">PyScadeOne<\/a> library connects the product with the full Python ecosystem.<\/p>\n<p>In this article, we will explore how to leverage <strong>pytest<\/strong> to set up a highly efficient workflow for building, verifying, and maintaining high-assurance embedded software.<\/p>\n<h3  id=\"PYSCADEONE-THE-PYTHON-BRIDGE-TO-YOUR-MODELS\">PyScadeOne: the Python bridge to your models<\/h3>\n<p>At the heart of integrating Scade One models with Python is <a href=\"https:\/\/scadeone.docs.pyansys.com\/\">PyScadeOne<\/a>, a Python library that provides APIs to trigger IDE features. This includes browsing, navigating and editing Scade One models, launching jobs such as code generation and FMI 2.0 export, and encapsulating the generated code into a Python-accessible wrapper.<\/p>\n<p>This library is documented with examples and enables a smooth workflow that brings your model directly into Python for testing, simulation, and automation.<\/p>\n<p>PyScadeOne is published as free, open source software (MIT license) under the <a href=\"https:\/\/docs.pyansys.com\/\">PyAnsys<\/a> initiative.<\/p>\n<h3  id=\"EXPORTING-SCADE-ONE-MODELS-AS-PYTHON-CALLABLE-CODE\">Exporting Scade One models as Python-callable code<\/h3>\n<p>Using the PyScadeOne&#8217;s <a href=\"https:\/\/scadeone.docs.pyansys.com\/version\/stable\/api\/svc\/pywrapper.html\">Python wrapper<\/a> functionality, you can export a Scade One model (in the Swan language) as a <strong>Python function<\/strong>. This process wraps C code generated by Scade One so it becomes directly callable from a Python script.<\/p>\n<p>Once this is done, you may use the rich Python ecosystem to write and run tests using pytest. Alternatively, you may also leverage Python libraries such as <strong>NumPy<\/strong>, <strong>SciPy<\/strong>, or <a href=\"https:\/\/innovationspace.ansys.com\/knowledge\/forums\/topic\/jupyter-notebook-programming-with-the-scade-python-wrapper\/\">Jupyter Notebooks<\/a> for simulation, analysis, and reporting.<\/p>\n<p>In other words, your model becomes a first-class citizen in the Python ecosystem.<\/p>\n<h3  id=\"ENTER-PYTEST\">Enter pytest<\/h3>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2026\/02\/scade-058-pytest-logo-1.svg\" style=\"max-height: 200px !important\" \/><br \/>\n    <em><\/em>\n<\/p>\n<p><a href=\"https:\/\/pytest.org\/\">Pytest<\/a> is one of the most widely used Python testing frameworks, known for its simplicity and power. We will use it in this article, although the workflow we illustrate here would work with any Python-based testing framework.<\/p>\n<p>Pytest features a <strong>simple syntax<\/strong> using plain <code>assert<\/code> keywords. Test discovery is automatic (<code>test_*.py<\/code> files are tests by convention), and the library is extensible via plugins.<\/p>\n<p>For complex test setups, pytest provides<strong> rich fixtures<\/strong> as well as<strong> parameterization<\/strong> for running multiple test scenarios automatically.<\/p>\n<p>Finally, pytest can generate <strong>detailed HTML or JUnit reports<\/strong> and <strong>integrates easily with CI\/CD pipelines<\/strong>.<\/p>\n<p>When paired with PyScadeOne, pytest becomes a seamless testing layer over your Scade One models.<\/p>\n<h3  id=\"WORKFLOW-OVERVIEW\">Workflow overview<\/h3>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2026\/02\/scade-058-workflow-1.svg\" style=\"max-height: 400px !important\" \/><br \/>\n    <em><\/em>\n<\/p>\n<p>The development and testing loop looks like this:<\/p>\n<ul>\n<li><strong>Design and debug your models<\/strong> in Scade One<\/li>\n<li><strong>Generate code<\/strong> (via Scade One jobs or command line)<\/li>\n<li><strong>Generate a Python wrapper<\/strong> (DLL + Python proxy classes)<\/li>\n<li><strong>Write tests<\/strong> using pytest<\/li>\n<li><strong>Run tests<\/strong> and analyze logs &amp; reports<\/li>\n<\/ul>\n<p>The Python wrapper acts as a <strong>proxy<\/strong> to the generated C code: it sets inputs, call the cycle function, and retrieves outputs. Everything is callable directly from Python, enabling fast test iteration.<\/p>\n<p>In a way, the Python wrapper behaves similarly to a Functional Mock-up Unit (FMU). The Scade One model&#8217;s generated code is pre-compiled and wrapped in a neat package that can be called externally.<\/p>\n<h3  id=\"SETTING-UP-A-SCADE-ONE-PYTEST-PROJECT\">Setting up a Scade One + pytest project<\/h3>\n<p>First, <strong>prepare the operators<\/strong> you want to test and define job configurations for generating their C code:<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2026\/02\/scade-058-code-gen-jobs.png\" style=\"max-height: 500px !important\" \/><br \/>\n    <em><\/em>\n<\/p>\n<p>Next, <strong>organize your project structure<\/strong>. You may place your <code>tests\/<\/code> folder next to your model, e.g.:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span>\ud83d\udcc2 myproject\/\r\n    \ud83d\udcc2 assets\/\r\n    \ud83d\udcc2 jobs\/\r\n    \ud83d\udcc2 resources\/\r\n    \ud83d\uddce model.sproj\r\n\ud83d\udcc2 tests\/\r\n<\/pre>\n<\/div>\n<p>Inside the <code>tests\/<\/code> folder, create a <code>requirements.txt<\/code> file containing the following:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span>pytest\r\npytest<span style=\"font-weight: bold\">-<\/span>html\r\nmatplotlib\r\nansys<span style=\"font-weight: bold\">-<\/span>scadeone<span style=\"font-weight: bold\">-<\/span>core\r\n<\/pre>\n<\/div>\n<p>Next, <strong>prepare a Python virtual environment<\/strong> (a.k.a. &#8220;venv&#8221;). Here&#8217;s an example using Windows PowerShell:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span>python -m venv .venv\r\n.venv\\Scripts\\Activate.ps1\r\npython -m pip install -r tests\/requirements.txt\r\n<\/pre>\n<\/div>\n<p>This installs: PyScadeOne, pytest and any additional dependencies (plotting, HTML report generation) in a fresh, contained Python environment. You don&#8217;t need to worry about interactions with pre-installed libraries that may have the wrong version or interfere with running the tests.<\/p>\n<h3  id=\"AUTOMATICALLY-GENERATING-PYTHON-WRAPPERS\">Automatically generating Python wrappers<\/h3>\n<p>The next step is to <strong>generate C code<\/strong> and <strong>Python wrappers<\/strong> from your Scade One operators.<\/p>\n<p>Wrappers can be generated either by launching Scade One in batch mode from the<strong> command line<\/strong>, or<strong> directly from the PyScadeOne API<\/strong>:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span><span style=\"color: #999988;font-style: italic\"># Create a PythonWrapper instance<\/span>\r\nwrapper <span style=\"font-weight: bold\">=<\/span> PythonWrapper(project, job_name, proxy_name, target_path)\r\nwrapper<span style=\"font-weight: bold\">.<\/span>generate()\r\n<\/pre>\n<\/div>\n<p>For each operator, the wrapper generates:<\/p>\n<ul>\n<li>A class called <code>%operator%_%wrapper%<\/code><\/li>\n<li><code>reset<\/code> and <code>cycle<\/code> functions<\/li>\n<li>Strongly typed input and output structures<\/li>\n<\/ul>\n<p>When using pytest, a good practice is to place wrapper generation inside a fixture, so that the DLL and proxy classes are created automatically when tests run. This way, no manual setup is needed and each test has access to the operator under test.<\/p>\n<p>Below is an example of a pytest fixture that retrieves a Scade One project, generates the code and invokes the Python wrapper. Note that in real-life scenario, you may want to introduce more parameters to control whether the code \/ DLL need to be regenerated and accelerate test runs.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span><span style=\"font-weight: bold\">def<\/span> <span style=\"color: #990000;font-weight: bold\">_build_proxy<\/span>(project_dir: Path, job_name: <span style=\"color: #999999\">str<\/span>,wrapper_name: <span style=\"color: #999999\">str<\/span>,out_dir:<span style=\"color: #999999\">str<\/span>) <span style=\"font-weight: bold\">-&gt;<\/span> <span style=\"color: #999999\">bool<\/span>:\r\n    s_one_install <span style=\"font-weight: bold\">=<\/span> Path(<span style=\"color: #bb8844\">r&quot;C:\\Program Files\\ANSYS Inc\\v252\\Scade One&quot;<\/span>)\r\n    <span style=\"color: #999999\">print<\/span>(<span style=\"color: #bb8844\">&quot;Project path is {} &quot;<\/span><span style=\"font-weight: bold\">.<\/span>format(project_dir))\r\n    app <span style=\"font-weight: bold\">=<\/span> ScadeOne(install_dir<span style=\"font-weight: bold\">=<\/span>s_one_install)\r\n    prj <span style=\"font-weight: bold\">=<\/span> app<span style=\"font-weight: bold\">.<\/span>load_project(project_dir)\r\n    prj<span style=\"font-weight: bold\">.<\/span>load_jobs()\r\n    job <span style=\"font-weight: bold\">=<\/span> prj<span style=\"font-weight: bold\">.<\/span>get_job(job_name)\r\n    result <span style=\"font-weight: bold\">=<\/span> job<span style=\"font-weight: bold\">.<\/span>run()\r\n    <span style=\"font-weight: bold\">assert<\/span> result<span style=\"font-weight: bold\">.<\/span>code <span style=\"font-weight: bold\">==<\/span> <span style=\"color: #009999\">0<\/span>\r\n    gen <span style=\"font-weight: bold\">=<\/span> PythonWrapper(project<span style=\"font-weight: bold\">=<\/span>prj,job<span style=\"font-weight: bold\">=<\/span>job_name, output<span style=\"font-weight: bold\">=<\/span>wrapper_name,target_dir<span style=\"font-weight: bold\">=<\/span>out_dir)\r\n    gen<span style=\"font-weight: bold\">.<\/span>generate()\r\n    <span style=\"color: #999988;font-style: italic\"># add the target directory to sys.path<\/span>\r\n    <span style=\"font-weight: bold\">if<\/span> os<span style=\"font-weight: bold\">.<\/span>path<span style=\"font-weight: bold\">.<\/span>abspath(Path(out_dir<span style=\"font-weight: bold\">+<\/span><span style=\"color: #bb8844\">&quot;\/&quot;<\/span><span style=\"font-weight: bold\">+<\/span>wrapper_name)) <span style=\"font-weight: bold\">not<\/span> <span style=\"font-weight: bold\">in<\/span> sys<span style=\"font-weight: bold\">.<\/span>path:\r\n        sys<span style=\"font-weight: bold\">.<\/span>path<span style=\"font-weight: bold\">.<\/span>append(os<span style=\"font-weight: bold\">.<\/span>path<span style=\"font-weight: bold\">.<\/span>abspath(Path(out_dir<span style=\"font-weight: bold\">+<\/span><span style=\"color: #bb8844\">&quot;\/&quot;<\/span><span style=\"font-weight: bold\">+<\/span>wrapper_name)))\r\n     dll <span style=\"font-weight: bold\">=<\/span> Path(out_dir<span style=\"font-weight: bold\">+<\/span><span style=\"color: #bb8844\">&quot;\/&quot;<\/span><span style=\"font-weight: bold\">+<\/span>wrapper_name<span style=\"font-weight: bold\">+<\/span><span style=\"color: #bb8844\">&quot;\/&quot;<\/span><span style=\"font-weight: bold\">+<\/span> <span style=\"color: #bb8844\">&#039;%s.dll&#039;<\/span> <span style=\"font-weight: bold\">%<\/span> wrapper_name)\r\n    <span style=\"color: #999999\">print<\/span>(<span style=\"color: #bb8844\">&quot;Expecting dll in %s &quot;<\/span> <span style=\"font-weight: bold\">%<\/span> dll)\r\n    <span style=\"font-weight: bold\">return<\/span> dll<span style=\"font-weight: bold\">.<\/span>exists()\r\n\r\n@pytest<span style=\"font-weight: bold\">.<\/span>fixture(scope<span style=\"font-weight: bold\">=<\/span><span style=\"color: #bb8844\">&#039;session&#039;<\/span>) \r\n<span style=\"font-weight: bold\">def<\/span> <span style=\"color: #990000;font-weight: bold\">check_cc_proxy<\/span>() <span style=\"font-weight: bold\">-&gt;<\/span> <span style=\"color: #999999\">bool<\/span>: \r\n<span style=\"color: #bb8844\">&quot;&quot;&quot;Ensure the proxy is built and up-to-date.&quot;&quot;&quot;<\/span> \r\n    project_dir <span style=\"font-weight: bold\">=<\/span> Path(file)<span style=\"font-weight: bold\">.<\/span>parent<span style=\"font-weight: bold\">.<\/span>parent<span style=\"font-weight: bold\">.<\/span>parent <span style=\"font-weight: bold\">\/<\/span> <span style=\"color: #bb8844\">&#039;CruiseControl&#039;<\/span><span style=\"font-weight: bold\">\/<\/span> <span style=\"color: #bb8844\">&#039;CruiseControl.sproj&#039;<\/span> \r\n    <span style=\"font-weight: bold\">return<\/span> _build_proxy(project_dir, <span style=\"color: #bb8844\">&quot;CCCodeGenerationJob&quot;<\/span>,<span style=\"color: #bb8844\">&quot;cc&quot;<\/span>,<span style=\"color: #bb8844\">&quot;Tests\/proxy&quot;<\/span>)\r\n<\/pre>\n<\/div>\n<h3  id=\"DEVELOPING-TESTS-WITH-PYTEST\">Developing tests with PyTest<\/h3>\n<p>Writing a test procedure is straightforward. Start by creating a <code>tests\/test_%something%.py<\/code> file and instantiate the proxy class representing your operator using a fixture. Within each test, you can freely combine basic operations: resetting the model, setting inputs, running cycles, and asserting outputs.<\/p>\n<p>A typical flow begins by calling <code>reset()<\/code> to ensure a clean initial state. From there, set any required inputs to establish the desired starting conditions. Then, apply test-specific inputs and invoke the operator&#8217;s logic by calling <code>cycle()<\/code> as many times as needed. At any point, after <code>cycle()<\/code>, you can validate behavior by asserting output values with <code>assert<\/code>:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span> <span style=\"font-weight: bold\">def<\/span> <span style=\"color: #990000;font-weight: bold\">test_controller_integration<\/span>(check_cc_proxy):\r\n    <span style=\"color: #999988;font-style: italic\"># TC_CC_I_002<\/span>\r\n    <span style=\"font-weight: bold\">assert<\/span> check_cc_proxy\r\n    <span style=\"color: #999988;font-style: italic\"># check_csm_proxy adds the cc module directory to sys.path<\/span>\r\n    <span style=\"font-weight: bold\">from<\/span> <span style=\"color: #555555\">cc<\/span> <span style=\"font-weight: bold\">import<\/span> Controller\r\n    root <span style=\"font-weight: bold\">=<\/span> Controller()\r\n    root<span style=\"font-weight: bold\">.<\/span>reset()\r\n    <span style=\"color: #999988;font-style: italic\"># set the initial values for the commands<\/span>\r\n    root<span style=\"font-weight: bold\">.<\/span>on <span style=\"font-weight: bold\">=<\/span> <span style=\"font-weight: bold\">False<\/span>\r\n    root<span style=\"font-weight: bold\">.<\/span>off <span style=\"font-weight: bold\">=<\/span> <span style=\"font-weight: bold\">False<\/span>\r\n    root<span style=\"font-weight: bold\">.<\/span>resume_ <span style=\"font-weight: bold\">=<\/span> <span style=\"font-weight: bold\">False<\/span>\r\n    root<span style=\"font-weight: bold\">.<\/span>set <span style=\"font-weight: bold\">=<\/span> <span style=\"font-weight: bold\">False<\/span>\r\n    root<span style=\"font-weight: bold\">.<\/span>speed <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #009999\">0.0<\/span>\r\n    root<span style=\"font-weight: bold\">.<\/span>accel <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #009999\">0.0<\/span>\r\n    root<span style=\"font-weight: bold\">.<\/span>brake <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #009999\">0.0<\/span>\r\n    root<span style=\"font-weight: bold\">.<\/span>quickAccel<span style=\"font-weight: bold\">=<\/span> <span style=\"font-weight: bold\">False<\/span>\r\n    root<span style=\"font-weight: bold\">.<\/span>quickDecel<span style=\"font-weight: bold\">=<\/span> <span style=\"font-weight: bold\">False<\/span>\r\n\r\n    <span style=\"color: #999988;font-style: italic\"># Test Reference: CC_TEST_INT_01<\/span>\r\n    <span style=\"color: #999988;font-style: italic\">#<\/span>\r\n    <span style=\"color: #999988;font-style: italic\"># Test Case Objectives:<\/span>\r\n    <span style=\"color: #999988;font-style: italic\">#    verify the CC is started in STDBY mode when activated<\/span>\r\n    <span style=\"color: #999988;font-style: italic\">#    while the driver accelerates.<\/span>\r\n    <span style=\"color: #999988;font-style: italic\">#<\/span>\r\n    <span style=\"color: #999988;font-style: italic\"># Test Case Acceptance Criteria:<\/span>\r\n    <span style=\"color: #999988;font-style: italic\">#    cruiseState is STDBY, throttleCmd = accel,<\/span>\r\n    <span style=\"color: #999988;font-style: italic\">#    and cruiseSpeed = speed<\/span>\r\n    root<span style=\"font-weight: bold\">.<\/span>speed <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #009999\">100.0<\/span>\r\n    root<span style=\"font-weight: bold\">.<\/span>accel <span style=\"font-weight: bold\">=<\/span> <span style=\"color: #009999\">25.0<\/span>\r\n    root<span style=\"font-weight: bold\">.<\/span>on <span style=\"font-weight: bold\">=<\/span> <span style=\"font-weight: bold\">True<\/span>\r\n    root<span style=\"font-weight: bold\">.<\/span>cycle()\r\n    <span style=\"font-weight: bold\">assert<\/span> root<span style=\"font-weight: bold\">.<\/span>cruiseState <span style=\"font-weight: bold\">==<\/span> CC_STATE<span style=\"font-weight: bold\">.<\/span>STDBY<span style=\"font-weight: bold\">.<\/span>value\r\n    <span style=\"font-weight: bold\">assert<\/span> <span style=\"color: #999999\">abs<\/span>(root<span style=\"font-weight: bold\">.<\/span>throttleCmd <span style=\"font-weight: bold\">-<\/span> root<span style=\"font-weight: bold\">.<\/span>accel) <span style=\"font-weight: bold\">&lt;<\/span> <span style=\"color: #009999\">5.0e-6<\/span>\r\n    <span style=\"font-weight: bold\">assert<\/span> <span style=\"color: #999999\">abs<\/span>(root<span style=\"font-weight: bold\">.<\/span>cruiseSpeed <span style=\"font-weight: bold\">-<\/span> root<span style=\"font-weight: bold\">.<\/span>speed) <span style=\"font-weight: bold\">&lt;<\/span> <span style=\"color: #009999\">5.0e-6<\/span>\r\n<\/pre>\n<\/div>\n<h3  id=\"RUNNING-TESTS\">Running tests<\/h3>\n<p>Pytest allows you to:<\/p>\n<ul>\n<li>Run all tests in a folder:<\/li>\n<\/ul>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span>&gt; pytest tests\\\r\n<\/pre>\n<\/div>\n<ul>\n<li>Run a single test file:<\/li>\n<\/ul>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow:auto;width:auto;background:none;border:none;padding:.2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\"><span><\/span>&gt; pytest .\\tests\\test_cc.py\r\n<\/pre>\n<\/div>\n<ul>\n<li>Filter using keywords or markers<\/li>\n<li>Run from the CLI or directly from IDEs like Visual Studio Code:<\/li>\n<\/ul>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2026\/02\/scade-058-vscode-test-run.png\" style=\"max-height: 300px !important\" \/><br \/>\n    <em>Running tests from VSCode<\/em>\n<\/p>\n<p>Pytest may generate reports in <a href=\"https:\/\/pytest-html.readthedocs.io\/en\/latest\/\">HTML<\/a> or <a href=\"https:\/\/docs.pytest.org\/en\/7.1.x\/how-to\/output.html#creating-junitxml-format-files\">JUnit<\/a> formats, which can easily be imported into test management tools:<\/p>\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2026\/02\/scade-058-pytest-report.png\" style=\"max-height: 400px !important\" \/><br \/>\n    <em>Sample HTML report generated with <code>pytest-html<\/code><\/em>\n<\/p>\n<h3  id=\"READY-TO-TRY-THIS-OUT\">Ready to try this out?<\/h3>\n<p>In this article, we saw how to combine <strong>Scade One<\/strong>, <strong>PyScadeOne<\/strong>, and <strong>pytest<\/strong> to unlock a powerful, modern, and highly automated workflow for testing embedded software models. We get:<\/p>\n<ul>\n<li>Scade One&#8217;s robust modeling and code generation<\/li>\n<li>Python&#8217;s productivity and tooling ecosystem<\/li>\n<li>Scalable, maintainable testing pipelines<\/li>\n<li>Rich reporting and easy to export results<\/li>\n<\/ul>\n<p>This integration is ideal for cost-critical embedded systems that must meet the highest testing standards.<\/p>\n<p>If you are a Scade One user and would like to play with this concept, you may download an example model <a href=\"https:\/\/github.com\/ansys\/scadeone-examples\/releases\/latest\/download\/2026-02-17-pytest.zip\">here<\/a>.<\/p>\n<p>If you are a SCADE user, you may <a href=\"https:\/\/download.ansys.com\/embedded-software\">try out<\/a> Scade One at no extra cost with your existing licenses.<\/p>\n<h3  id=\"ABOUT-THE-AUTHOR\">About the author<\/h3>\n<table style=\"max-width: 1000px;border: none !important\">\n<tr>\n<td style=\"padding: 0px 10px;min-width: 150px;border: none !important\">\n<p style=\"text-align: center\">\n    <img decoding=\"async\" src=\"https:\/\/innovationspace.ansys.com\/knowledge\/wp-content\/uploads\/sites\/4\/2026\/02\/scade-058-author.png\" style=\"max-height: 150px !important\" \/><br \/>\n                <em><\/em>\n<\/p>\n<\/td>\n<td style=\"padding: 0px 10px;min-width: 150px;border: none !important\">\n<p><strong>Romain Andrieux<\/strong> (<a href=\"https:\/\/www.linkedin.com\/in\/romain-andrieux-922a36103\">LinkedIn<\/a>) is a Product Specialist Engineer at Ansys. He has been working on SCADE Ecosystem and the SCADE Support team development for 2 years.<\/p>\n<\/td>\n<\/tr>\n<\/table>\n","protected":false},"template":"","class_list":["post-197952","topic","type-topic","status-publish","hentry","topic-tag-pyansys","topic-tag-pyscadeone","topic-tag-pytest","topic-tag-python","topic-tag-scade-one","topic-tag-testing"],"aioseo_notices":[],"acf":[],"custom_fields":[{"0":{"_edit_lock":["1773231017:1769"],"_edit_last":["1769"],"_aioseo_title":[null],"_aioseo_description":[null],"_aioseo_keywords":["a:0:{}"],"_aioseo_og_title":[null],"_aioseo_og_description":[null],"_aioseo_og_article_section":[""],"_aioseo_og_article_tags":["a:0:{}"],"_aioseo_twitter_title":[null],"_aioseo_twitter_description":[null],"filter_by_optics_product":["Lumerical"],"_filter_by_optics_product":["field_64fb192ba3121"],"application_name":[""],"_application_name":["field_64a80903c8e15"],"family":[""],"_family":["field_64a809229a857"],"siebel_km_number":[""],"_siebel_km_number":["field_63ecbffce60db"],"salesforce_km_number":[""],"_salesforce_km_number":["field_63ecc018e60dc"],"km_published_date":[""],"_km_published_date":["field_64c77704499dd"],"product_version":[""],"_product_version":["field_64c776cb4fd2e"],"_bbp_forum_id":["27825"],"_bbp_topic_id":["197964"],"_bbp_author_ip":["13.82.168.84"],"_bbp_last_reply_id":["0"],"_bbp_last_active_id":["197953"],"_bbp_last_active_time":["2026-02-17 09:06:42"],"_bbp_reply_count":["0"],"_bbp_reply_count_hidden":["0"],"_bbp_voice_count":["0"],"_btv_view_count":["218"],"_bbp_likes_count":["3"]},"test":"solution"}],"_links":{"self":[{"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/topics\/197952","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/topics"}],"about":[{"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/types\/topic"}],"version-history":[{"count":7,"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/topics\/197952\/revisions"}],"predecessor-version":[{"id":197964,"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/topics\/197952\/revisions\/197964"}],"wp:attachment":[{"href":"https:\/\/innovationspace.ansys.com\/knowledge\/wp-json\/wp\/v2\/media?parent=197952"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}