Three changes, all driven by what the camera actually did. info.cgi must not carry the session id -------------------------------------- Hardware run on 2026-08-17: get_camera_info() succeeded but every position lookup raised "axis 'pan' (c.1.pan) not in info.cgi response". Bare info.cgi returns the full ~32 kB device state; `info.cgi?s=<id>` returns only the session-scoped `s.*` subset -- which contains s.hardware and s.firmware, so identity worked while nothing under c.1.* existed. The session parameter is now omitted for info.cgi (and open.cgi, as before); control CGIs still carry it. This is what unblocks Stages 2 and 3. Drop the mjpeg acquisition mode ------------------------------- The CR-N300 implements no MJPEG operator -- nphMotionJpeg, GetLiveImage and the rest all answer "Unknown Operator" -- so the mode could never have produced a frame here. Removed rather than left as a config value that silently does nothing: ACQUISITION_MODES is now (jpeg_poll, jpeg_on_demand), and MJPEGHttpSource, the stream_url key and DEFAULT_STREAM_CGI go with it. Re-adding a streaming mode means writing one FrameSource; the worker, ring buffer and grab API are indifferent to how frames arrive. The JPEG path is 1280x720 at up to 12.5 fps (w.3); 4K is H.264-only, so nobody should expect full-resolution frames through the grab API. acquisition_check.py -- the Stage 7 tool ----------------------------------------- Drives the production acquisition path (SingleJpegPollSource + StreamWorker + FrameRingBuffer) and reports establishment time, achieved rate, measured bandwidth, grab latency and -- with --decode -- a real cv2 decode with its resolution. Standard-library only and runnable from a copied canon/ directory, like probe.py, so it works before BEC is installed on a beamline machine. It is read-only, which means **Stage 7 does not depend on Stage 4**: the whole acquisition path can be closed with the camera still on the bench, waiting to be mounted. COMMISSIONING gains this as step 7.0b. Tests: 86. New coverage for the sessionless info.cgi (regression for the exact hardware failure), mjpeg now being rejected at construction, and the Stage 7 tool end-to-end against the mock camera including its non-zero exit when nothing answers. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Getting Started with Testing using pytest
BEC is using the pytest framework. It can be installed via
pip install pytest
in your python environment.
We note that pytest is part of the optional-dependencies [dev] of the plugin package.
Introduction
Tests in this package should be stored in the tests directory.
We suggest to sort tests of different submodules, i.e. scans or devices in the respective folder structure, and to folow a naming convention of <test_module_name.py>.
It is mandatory for test files to begin with test_ for pytest to discover them.
To run all tests, navigate to the directory of the plugin from the command line, and run the command
pytest -v --random-order ./tests
Note, the python environment needs to be active.
The additional arg -v allows pytest to run in verbose mode which provides more detailed information about the tests being run.
The argument --random-order instructs pytest to run the tests in random order, which is the default in the CI pipelines.
Test examples
Writing tests can be quite specific for the given function. We recommend writing tests as isolated as possible, i.e. try to test single functions instead of full classes. A very useful class to enable isolated testing is MagicMock. In addition, we also recommend to take a look at the How-to guides from pytest.