Automated Testing, Pytest & GitHub Actions CI/CD | Mycroft AI

This video shows how automated tests and continuous integration improve the reliability of the Provenance Gatekeeper in the Mycroft AI project. Pytest codifies adversarial cases, and GitHub Actions runs them on every push so failing builds cannot merge.

2:11 video3 min readWatch on YouTube

Software that works on a local machine is not the same as software that survives production. This video from the Humanitarians AI series follows the seventh week of the Mycroft AI project. The previous week produced a parser for the Provenance Gatekeeper that extracts financial data from unpredictable AI text. This week added no new detection logic at all. It added the suite that makes last week's logic trustworthy next month by running itself on a machine that is not the developer's, every time anyone touches the code.

Replacing manual checks with Pytest

The first step was writing strict unit tests with Pytest, collected in a test_main.py file. Each adversarial scenario the team knew about was codified: valid strings, magnitude errors, and SQL injections. Instead of running scripts by hand and eyeballing the output, there is now a programmatic harness that shows the normalization layer behaves as intended.

Removing the human with GitHub Actions

Developers forget to run tests, so the second step was integrating GitHub Actions. The workflow uses path filtering, which means every time new code is pushed to the Gatekeeper directory, GitHub starts a clean Ubuntu runner and installs the dependencies. It then boots the FastAPI and Chroma DB architecture inside Docker.

The adversarial stress test in the pipeline

Once the environment is live, the pipeline bombards the project's own API with the adversarial stress test. If a single hallucinated payload slips through the logic, the build fails and the code is blocked from merging. The video demonstrates this with a pull request designed to let one hallucinated payload through, to see whether the pipeline would let it reach the main branch. The result is a perimeter that regressions cannot cross into main. The demonstration is tied to Pull Request 62.

Why automation matters

The video's slogan is that unautomated security is just a suggestion, and a test you have to remember to run is not a test. The advice is to stop testing AI logic by hand, write unit tests for the extraction layer, and force the repository to run them on every commit.

A caution about the suite itself

The video ends with a warning about what automated tests cannot do. A suite that only contains the attacks you have already thought of will pass forever, right up until it matters. Once the pipeline is green, the suggestion is to find the attack categories with no tests at all.

Key takeaways

  • Working locally is not the same as surviving production.
  • Pytest can codify adversarial cases such as valid strings, magnitude errors and SQL injections.
  • GitHub Actions can run those tests on every push so no one has to remember.
  • Path filtering limits the workflow to changes in the relevant directory.
  • The pipeline starts a clean Ubuntu runner and runs FastAPI and Chroma DB in Docker.
  • If any hallucinated payload gets through, the build fails and the merge is blocked.
  • A suite limited to known attacks gives false comfort.

Try it yourself

Once your pipeline is green, give a model your test file and your parser. Ask which adversarial categories you have no test for at all. Then add tests for those categories so the suite does not simply reflect the attacks you already thought of.

Full transcript(auto-generated, with timestamps)

[0:00]Hi, I am Onkar Budhpal. Last week we built a rejects parser for the Provenance Gatekeeper that extracts financial data from unpredictable AI text. It worked perfectly on my local machine, but enterprise software is not about what works locally. It is about what survives in production. This week we strip away manual testing and build an automated continuous integration pipeline. Week seven added no new detection logic at all. It added the thing that makes last week's logic trustworthy next month, a suite that runs itself on a machine that is not mine every single time anyone touches the code. We started by writing strict unit tests with Pytest. We codified every adversarial

[0:37]Scenario we knew of valid strings, magnitude errors, SQL injections into a test_main.py file. Instead of running scripts by hand and eyeballing the output, we now have a programmatic harness that proves the normalization layer behaves exactly as intended. But developers forget to run tests. To remove the human, we integrated GitHub actions. We configured a workflow with path filtering, so every time new code is pushed to the Gatekeeper directory, GitHub spins up a pristine Ubuntu runner, installs our dependencies, and boots the FastAPI and Chroma DB architecture inside Docker. So, let's push a pull request that lets one hallucinated payload through and watch whether the pipeline lets it reach

[1:18]The main branch. Once the environment is live, the pipeline bombards our own API with the adversarial stress test. If a single hallucinated payload slips through the logic, the build fails and the code is blocked from merging. We have effectively built a perimeter that regressions cannot physically cross into the main branch. So, stop testing your AI logic by hand. Write unit tests for your extraction layer and force your repository to run them on every commit. Unautomated security is just a suggestion. And once the pipeline is green, here is the prompt worth running. Give a model your test file and your parser and ask which adversarial categories you have no

[1:55]Test for at all. A suite that only contains the attacks you already thought of will pass forever right up until it matters. A test you have to remember to run is not a test. Unautomated security is just a suggestion. Onkar Bujable for Humanitarian's AI.

More from Mycroft Financial AI

Humanitarians AI Lyrical Literacy Project