Testing PlotJuggler Data Visualization Integration in OpenPilot
This test suite validates the functionality of PlotJuggler integration in the OpenPilot project, focusing on demo route playback and layout validation. It ensures proper data visualization and layout handling while preventing common integration issues.
Test Coverage Overview
Implementation Analysis
Technical Details
Best Practices Demonstrated
commaai/openpilot
tools/plotjuggler/test_plotjuggler.py
import os
import glob
import signal
import subprocess
import time
from openpilot.common.basedir import BASEDIR
from openpilot.common.timeout import Timeout
from openpilot.tools.plotjuggler.juggle import DEMO_ROUTE, install
PJ_DIR = os.path.join(BASEDIR, "tools/plotjuggler")
class TestPlotJuggler:
def test_demo(self):
install()
pj = os.path.join(PJ_DIR, "juggle.py")
with subprocess.Popen(f'QT_QPA_PLATFORM=offscreen {pj} "{DEMO_ROUTE}/:2"',
stderr=subprocess.PIPE, shell=True, start_new_session=True) as p:
# Wait for "Done reading Rlog data" signal from the plugin
output = "
"
with Timeout(180, error_msg=output):
while output.splitlines()[-1] != "Done reading Rlog data":
output += p.stderr.readline().decode("utf-8")
# ensure plotjuggler didn't crash after exiting the plugin
time.sleep(2)
assert p.poll() is None
os.killpg(os.getpgid(p.pid), signal.SIGTERM)
assert "Raw file read failed" not in output
# TODO: also test that layouts successfully load
def test_layouts(self, subtests):
bad_strings = (
# if a previously loaded file is defined,
# PJ will throw a warning when loading the layout
"fileInfo",
"previouslyLoaded_Datafiles",
)
for fn in glob.glob(os.path.join(PJ_DIR, "layouts/*")):
name = os.path.basename(fn)
with subtests.test(layout=name):
with open(fn) as f:
layout = f.read()
violations = [s for s in bad_strings if s in layout]
assert len(violations) == 0, f"These should be stripped out of the layout: {str(violations)}"