{"id":46260259,"url":"https://github.com/insys-icom/medusa","last_synced_at":"2026-03-04T01:28:33.424Z","repository":{"id":340318174,"uuid":"1143383483","full_name":"insys-icom/medusa","owner":"insys-icom","description":"Easily run Robot Framework test suites in parallel.","archived":false,"fork":false,"pushed_at":"2026-02-24T08:30:31.000Z","size":62,"stargazers_count":7,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-24T14:40:02.013Z","etag":null,"topics":["python","robotframework","test-automation","testing"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/insys-icom.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-27T14:13:13.000Z","updated_at":"2026-02-24T08:30:30.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/insys-icom/medusa","commit_stats":null,"previous_names":["insys-icom/medusa"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/insys-icom/medusa","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insys-icom%2Fmedusa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insys-icom%2Fmedusa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insys-icom%2Fmedusa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insys-icom%2Fmedusa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/insys-icom","download_url":"https://codeload.github.com/insys-icom/medusa/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insys-icom%2Fmedusa/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30068360,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T01:03:42.280Z","status":"ssl_error","status_checked_at":"2026-03-04T01:03:23.410Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["python","robotframework","test-automation","testing"],"created_at":"2026-03-04T01:28:32.883Z","updated_at":"2026-03-04T01:28:33.387Z","avatar_url":"https://github.com/insys-icom.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Medusa\n\n___Medusa is a tool to easily parallelize execution of [Robot Framework](https://robotframework.org/) test suites.___\n\nIf you have a lot of Robot Framework tests that take a non-negligible amount of time, you can benefit greatly from running them in parallel. Medusa uses suite metadata to start suites in parallel dynamically while preventing resource usage conflicts. Suites can be assigned to sequentially executed stages and can be run multiple times with different variables, even in parallel.\n\nThis could be used to execute one or multiple suites against multiple target devices or endpoints simultaneously, or even to execute a single suite sequentially multiple times with different configuration.\n\nParallelization happens on suite level, it is not (currently) possible to run tests within a single suite in parallel. It is also not (currently) possible to have one suite directly depend on another suite to finish first, though you could use separate stages to achieve this. Consider using [pabot](https://pabot.org/) if you need these features.\n\nMedusa is developed by [INSYS icom GmbH](https://insys-icom.com) and licensed as Open Source Software, see the [License](#license) section below for details. INSYS icom does not provide support for Medusa, see [Reporting Bugs](#reporting-bugs) if you found a problem.\n\n\n# Table of Contents\n\n1. [Installation](#installation)\n    1. [User](#user)\n    1. [Developer](#developer)\n1. [Quick Start](#quick-start)\n1. [Command line usage](#command-line-usage)\n1. [Suite metadata](#suite-metadata)\n1. [Reporting bugs](#reporting-bugs)\n1. [Contributing features](#contributing-features)\n1. [License](#license)\n\n\n# Installation\n___NOTE: Medusa is currently only tested on Linux and does not work on Windows 11, see [#4](https://github.com/insys-icom/medusa/issues/4).___\n\nMake sure you have installed python3 `pip` and `venv`.\n\n## User\n``` sh\npython3 -m venv .venv  # Create a venv in .venv (if not done already)\n. .venv/bin/activate   # Enter the venv\n\n# Install medusa from PyPI.org\npython3 -m pip install robotframework-medusa\n# OR install it from source\npython3 -m pip install .\n\n# use medusa...\n\ndeactivate                # Exit the venv (when you are done)\n```\n\n## Developer\n``` sh\npython3 -m venv .venv  # Create a venv in .venv (if not done already)\n. .venv/bin/activate   # Enter the venv\npython3 -m pip install -e '.[dev]'  # Install editable with dev dependencies\n\n# use medusa, do your developing...\n\nmake format            # Run formatter\nmake check             # Run type checker and linter\nmake fix               # Auto-fix linter suggestions (if possible)\nmake test              # Run tests\ndeactivate             # Exit the venv (when you are done)\n```\n\n\n# Quick Start\nAdd at least the required metadata `medusa:stage` and `medusa:deps` to your suite(s). Optionally add `medusa:timeout` for suite-specific timeouts or `medusa:for` for multiplying suites with different variables.\n\n``` robot\n*** Settings ***\nDocumentation    Stage 1, multiply suite with three different dependencies and\n...              input values, timeout 5min (soft), 30s (hard), 5s (kill)\n...              First suite:  $DEP=foo    $INPUT=input1\n...              Second suite: $DEP=bar    $INPUT=input2\n...              Third suite:  $DEP=baz    $INPUT=input3\nMetadata    medusa:stage      1\nMetadata    medusa:deps       ${DEP}\nMetadata    medusa:for        ${DEP}    ${INPUT}    IN    \u0026{DEP_INPUT_DICT}\nMetadata    medusa:timeout    300,30,5\n\n*** Variables ***\n${DEP}               ${None}  # Set by medusa:for\n${INPUT}             ${None}  # Set by medusa:for\n\u0026{DEP_INPUT_DICT}    foo=input1    bar=input2    baz=input3\n```\n\nUsage summary:\n* `medusa stats`: View information about your suite(s)\n* `medusa run`: Run the suite(s)\n* Use robot options with `--` as a separator after medusa options: `medusa run -- -i security my_suite.robot`\n\nResults are stored in the `results/` directory in a date/timestamped subdirectory by default, this can be changed with the `-d` option. See `medusa -h` and the detailed documentation below for more information.\n\n\n# Command line usage\nRun `medusa --help` for full usage information, this section is just a rough overview. Medusa supports two main actions, `stats` and `run`. You can use `help` to get additional info about some options and `version` to output medusa's version.\n\nThe `stats` and `run` commands accept arguments just like `robot`. Example with just suites as arguments:\n``` sh\nmedusa stats single_suite.robot my_suite_dir/\n```\n\nYou can also use (almost) all options that `robot` accepts. You need to write `--` before any `robot` options in order to separate them from Medusa's own options. In this example, we use `robot`'s `--dryrun` option:\n``` sh\n#                     Separator ──┲┓\nmedusa run --outputdir customdir/ -- --dryrun my_suite_dir/\n#          ┗━━ Medusa Option ━━━┛    ┗━━━ Robot Option ━━━┛\n```\n\n## `medusa stats ...`\nMedusa reads the specified suite(s) and outputs information about them. By default, only a short summary of stats is given but more information can be shown with the `-s` or `--select` option. This includes infomation about recognised stages, dependencies and suites, as well as tags. Additional options:\n* Filter suites by stage/dependency with `-f` or `--filter`\n* Output additional information with `-s` or `--select`\n\n## `medusa run ...`\nMedusa reads the specified suite(s) and executes them. Stages are sorted alphabetically and executed sequentially. Within each stage, medusa dynamically starts as many suite in parallel as possible without starting suites with overlapping dependencies. Additional options:\n* Change the output directory with `-d` or `--outputdir`\n* Filter suites by stage/dependency with `-f` or `--filter`\n* Set global soft/hard/kill timeouts with `-t` or `--timeout` (can be overriden with suite metadata)\n\n# Suite metadata\nThe order and parallelisation of suites is determined entirely by suite metadata. For this reason, every suite needs to have at least `medusa:stage` and `medusa:deps` metadata configured. The `medusa:for` and `medusa:timeout` metadata is optional.\n\nThe below examples use the `$VAR` escaped variable syntax but the regular `${VAR}` syntax works too.\n\n## `medusa:stage` (required)\nEach suite needs to be assigned to a stage using the `medusa:stage` metadata key. Stages are executed sequentially in alphanumeric order, meaning that two suites in different stages will never run in parallel. After all suites in one stage finished executing, the next stage is executed.\n\nExample:\n```robot\n*** Settings ***\nMetadata    medusa:stage    1_Example\n```\n\nGiven these three suites:\n* _Suite1_ with `medusa:stage` = _1_Example_\n* _Suite2_ with `medusa:stage` = _1_Example_\n* _Suite3_ with `medusa:stage` = _2_Potato_\n\nThe suites _Suite1_ and _Suite2_ will be executed first, possibly in parallel (if their dependencies allow it). Once both of them finished, _Suite3_ will be executed.\n\n\n## `medusa:deps` (required)\nEach suite needs to declare dependencies using the `medusa:deps` metadata key. If two suites in the same stage have overlapping dependencies, they are not executed in parallel.\n\nExample:\n```robot\n*** Settings ***\nMetadata    medusa:deps    foo    ${BAR}    @{BAZ}\n\n*** Variables ***\n${BAR}    bar\n@{BAZ}    baz    buzz    butz\n```\n\nAs you can see, `medusa:deps` takes a list of values separated by two or more spaces. You can either directly write the value or use scalar or list variables. In the case of list variables, the list is simply flattened. This means that the above example is equivalent to:\n```robot\n*** Settings ***\nMetadata    medusa:deps    foo    bar    baz    buzz    butz\n```\n\nGiven these three suites in the same stage:\n* _Suite1_ with `medusa:deps` = _foo_, _bar_\n* _Suite2_ with `medusa:deps` = _bar_, _baz_\n* _Suite3_ with `medusa:deps` = _buzz_, _butz_\n\nThe suites _Suite1_ and _Suite2_ will not be executed in parallel because they both have the dependency _bar_. _Suite3_ will be executed in parallel to the other two because it does not have any dependencies in common with them.\n\n### Dynamic dependencies\nMedusa can also pick a dependency from a list of options at runtime, depending on whether one of the options is available. This can be done with the `ANY $ITEM IN $LIST` syntax. `$LIST` has to be a list variable and `$ITEM` needs to be defined with value `None` (`${None}` in Robot Framework) Here is an example for a suite that can run on any one device out of a list:\n```robot\n*** Settings ***\nMetadata    medusa:deps    ANY $DUT IN $DEVICES\n\n*** Variables\n@{DEVICES}    dut1    dut2    dut3  # List of options\n${DUT}    ${None}                   # Determined at runtime by medusa\n```\n\nWhen this suite is executed with medusa, `${DUT}` could have any one of the three values `dut1`, `dut2` or `dut3` depending on which ones is available (not currently used by another suite).\n\nDynamic dependencies can also be combined with `medusa:for`, for example in order to run the same suite on two devices from different lists of options.\n\n\n## `medusa:for` (optional)\nThe `medusa:for` metadata key can be used to execute one suite multiple times with differently set suite variables. This could be used to run the same test suite in parallel against multiple endpoints or test devices or with slightly differing configuration. `medusa:for` expects the format `$TARGET    [$TARGET...]    IN    $SOURCE`. The `$SOURCE` is either a list or dictionary of input values and the `$TARGET`s are variable names to assign the input values to. The target variables have to be declared with value `${None}`.\n\nExample with one target variable and simple input list:\n```robot\n*** Settings ***\nMetadata    medusa:for    $DUT    IN    $DUTS\n\n*** Variables ***\n@{DUTS}    foo    bar  # Source (input values)\n${DUT}    ${None}      # Target variable\n```\nThe above example suite will be executed twice, once with `${DUT}` = _foo_ and once with `${DUT}` = _bar_.\n\nExample with three target variables and two-dimensional input list:\n```robot\n*** Settings ***\nMetadata    medusa:for   $FIRST    $SECOND    $THIRD    IN    $RUNS\n\n*** Variables ***\n@{RUNS}      ${RUN1}    ${RUN2}\n\n# Targets:   FIRST  SECOND  THIRD\n@{RUN1}      one    two     three\n@{RUN2}      1      2       3\n\n${FIRST}     ${None}  # Set by medusa:for\n${SECOND}    ${None}  # Set by medusa:for\n${THIRD}     ${None}  # Set by medusa:for\n```\nThe above example suite will be executed twice:\n* Once with `${FIRST}` = _one_, `${SECOND}` = _two_, `${THIRD}` = _three_\n* Once with `${FIRST}` = _1_, `${SECOND}` = _2_, `${THIRD}` = _3_\n\n\nFinally, you can also use a dictionary as an input variable with two target variables:\n``` robot\n*** Settings ***\nMetadata    medusa:for    $DUT    $VAL    IN    $RUNS\n\n*** Variables ***\n# Targets:  DUT=VAL\n\u0026{DUTS}\n...         foo=one\n...         bar=two\n\n${DUT}      ${None}  # Set by medusa:for\n${VAL}      ${None}  # Set by medusa:for\n```\nThe above example suite will be executed twice:\n* Once with `${DUT}` = _foo_, `${VAL}` = _one_\n* Once with `${DUT}` = _bar_, `${VAL}` = _two_\n\n\n## `medusa:timeout` (optional)\nThe `medusa:timeout` metadata key can be used to set a suite-specific timeout. This timeout overrides the command-line option `-t`/`--timeout`. The value has the same format as the command-line option, see `medusa --help` for details.\n\nExample:\n``` robot\n*** Settings ***\nMetadata    medusa:timeout    300,60,5\n```\nThis results in a soft timeout of 300 seconds, a hard timeout of 60 seconds and a kill timeout of 5 seconds.\n\n\n## Complex example using all metadata\n``` robot\n*** Settings ***\nDocumentation    Using `medusa:for`, this suite is executed three times in two\n...    different stages and with different dependencies each time. The two\n...    executions in stage 0 are run in parallel since their dependencies don't\n...    overlap. One port is picked arbitrarily from a different list of ports\n...    in each run.\n...    The suite has a soft timeout of 300 seconds, a hard timeout of 30\n...    seconds and a kill timeout of 5 seconds.\nMetadata    medusa:for        $STAGE    $DUT1    $DUT2    $PORTS    IN    $RUNS\nMetadata    medusa:deps       $DUT1    $DUT2   ANY $PORT IN $PORTS\nMetadata    medusa:stage      $STAGE\nMetadata    medusa:timeout    300,30,5\n\n\n*** Variables ***\n@{RUNS}      ${RUN1}    ${RUN2}    ${RUN3}\n\n# Targets:   STAGE    DUT1     DUT2    PORTS\n@{RUN1}      0        one      two     ${PORTS1}\n@{RUN2}      0        three    four    ${PORTS2}\n@{RUN3}      1        one      four    ${PORTS3}\n\n@{PORTS1}    12      34      56\n@{PORTS2}    123     456     789\n@{PORTS3}    1234    5678    9012\n\n# Set by medusa:for\n${STAGE}     ${None}\n${DUT1}      ${None}\n${DUT2}      ${None}\n${PORTS}     ${None}\n\n# Set by medusa:deps (dynamic)\n${PORT}     ${None}\n\n\n*** Test Cases ***\nDo Something\n    Log    STAGE=${STAGE}, DUT1=${DUT1}, DUT2=${DUT2}, PORT=${PORT}\n```\n\n\n# Reporting bugs\nYou can report bugs by opening an [issue](https://github.com/insys-icom/medusa/issues) in GitHub or sending an Email to [unicorn@regrow.earth](mailto:unicorn@regrow.earth).\n\n\n# Contributing features\nIf you want to contribute code to Medusa, you can either open a [pull request](https://github.com/insys-icom/medusa/pulls) or [send a patch via Email](https://git-send-email.io/) to [unicorn@regrow.earth](mailto:unicorn@regrow.earth).\n\nA few things to note:\n* Contributions should follow the coding style of the rest of Medusa (or feel free to explicitly suggest improvements to the coding style).\n* Commits should have meaningful messages, naming the main file(s) that was/were changed and the change contents. If it's a bigger change, write more than just the first line. Example: `README: Fix missing comma` or `main: Add new command 'foo'`\n* Use `make check`, `make fix`, `make format` and `make test` and fix any issues before submitting your contribution.\n* When submitting a pull request or patch, ensure that your branch is up to date with the main branch.\n* You need to verify that you hold the rights to contribute the code under the applicable license, depending on whether you are contributing code and/or documentation (see below).\n\n\n# License\nMedusa is open source software licensed under the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0). Medusa documentation and other similar content use the [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/) license.\n\nSee [LICENSE](./LICENSE) for the full Apache-2.0 license text and [NOTICE](./NOTICE) for the full copyright notice.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finsys-icom%2Fmedusa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finsys-icom%2Fmedusa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finsys-icom%2Fmedusa/lists"}