Skip to content

Unit testing BpodSystem and protocol running locally and on GitHub Actions#37

Open
ogeesan wants to merge 43 commits intosanworks:developfrom
ogeesan:feature/protocol-unittest
Open

Unit testing BpodSystem and protocol running locally and on GitHub Actions#37
ogeesan wants to merge 43 commits intosanworks:developfrom
ogeesan:feature/protocol-unittest

Conversation

@ogeesan
Copy link
Contributor

@ogeesan ogeesan commented Aug 11, 2025

This PR introduces an integration test that runs a protocol in GitHub Actions, testing that a key user operation and all of the code components required to make it happen are able to integrate together.

This PR does three main things.

  1. Refactors RunProtocol and the LaunchManager into de-coupled pieces (i.e. no global BpodSystem), enabling usage in unit-testing.
  2. Enables running of core Bpod components without any GUI in a test context, allowing for testing in GitHub Actions.
  3. Introduces tests that involving the running of protocols both locally and on GitHub.

Launcher refactor

The old behaviour was:

  1. BpodSystem.GUIHandles.RunButton runs RunProtocol('StartPause')
  2. RunProtocol('StartPause') will run LaunchManager (if Bpod not being used)
  3. LaunchManager creates the GUI
  4. User makes selections of protocol folder and subject
  5. LaunchManager.launch_protocol() prepares state machine and calls run() to run the protocol (the function being similar to RunProtocol('Start'))

The repeated code in RunProtocol() and LaunchManager have been refactored, and now both call BpodLib.launcher.launchProtocol() to start a protocol.

Test Bpod

By creating a BpodObject without using InitializeGUI() we can get various runs to work on GitHub Actions. Using ~isempty(BpodSystem.GUIHandles) is used to make updating the GUI conditional on there being a GUI at all.

Protocol testing

Being able to run a protocol from start to finish serves as a good canary in the coal-mine for the testing suite. Our test coverage isn't very high right now, but by testing that many of the pieces are able to function together in their expected usage gives some good peace of mind.

Tests/assets/ now contains two protocols.

  • CoreTestProtocol.m - GUI-less protocol that runs locally and on GitHub Actions.
  • GUITestProtocol.m - Uses GUI elements (e.g. BpodSettingsGUI) and therefore can only run locally

ogeesan added 30 commits July 26, 2025 18:36
Prior to this the code assumed the protocol folder was in the top-level of the Protocols folder, meaning that the folders for the protocol would not be removed from the Path if it was a nested protocol.
If no COM is found the emulator dialog box is launched, and then the rest of the function runs. In that situation no BpodSystem is created and so the attempt to report on the calibration table fails.
The environment setup doesn't retain the path?
GH Actions says fileparts(which('Bpod')) is '/home/runner/work/Bpod_Gen2/Bpod_Gen2/Functions/Internal Functions/', so let's use the self-fixing function instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant