Skip to content

Commit 3926999

Browse files
Flex stacker pvt qc - Stallguard Test + current speed updates (#18511)
# Overview - Created a new folder to hold the final PVT/MP versions of the scripts - Created a new Stallguard test - Updated values of the current speed test to reflect DVT testing learnings - This is now a working base for further PVT diagnostic script updates and testing ## Test Plan and Hands on Testing - Tested function of all tests with Flex and DVT stacker running: - Robot server: 8.5.0-alpha.1 - Stacker FW: v0.0.7 ## Changelog - Created a new Stallguard test - Updated values of the current speed test to reflect DVT testing learnings ## Review requests ## Risk assessment
1 parent 85d8ffe commit 3926999

19 files changed

+1921
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""FLEX Stacker QC scripts."""
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
"""FLEX Stacker QC."""
2+
from os import environ
3+
4+
# NOTE: this is required to get WIFI test to work
5+
if "OT_SYSTEM_VERSION" not in environ:
6+
environ["OT_SYSTEM_VERSION"] = "0.0.0"
7+
8+
import argparse
9+
import asyncio
10+
import subprocess
11+
from pathlib import Path
12+
from typing import Tuple
13+
14+
from hardware_testing.data import ui
15+
from hardware_testing.data.csv_report import CSVReport
16+
17+
from .config import TestSection, TestConfig, build_report, TESTS
18+
from .driver import FlexStackerInterface, PlatformState
19+
20+
21+
async def build_stacker_report(
22+
is_simulating: bool,
23+
) -> Tuple[CSVReport, FlexStackerInterface]:
24+
"""Report setup for FLEX Stacker qc script."""
25+
test_name = Path(__file__).parent.name.replace("_", "-")
26+
ui.print_title(test_name.upper())
27+
28+
stacker = (
29+
await FlexStackerInterface.build_simulator()
30+
if is_simulating
31+
else await FlexStackerInterface.build()
32+
)
33+
34+
report = build_report(test_name)
35+
report.set_operator(
36+
"simulating" if is_simulating else input("enter OPERATOR name: ")
37+
)
38+
return report, stacker
39+
40+
41+
async def _main(cfg: TestConfig) -> None:
42+
# BUILD REPORT
43+
report, stacker = await build_stacker_report(cfg.simulate)
44+
45+
if not cfg.simulate:
46+
print("Stopping the robot server")
47+
subprocess.run(["systemctl stop opentrons-robot-server"], shell=True)
48+
# Perform initial checks before starting tests
49+
# 1. estop should not be pressed
50+
# 2. platform should be removed
51+
if await stacker.get_estop():
52+
ui.print_error("ESTOP is pressed, please release it before starting")
53+
ui.get_user_ready("Release ESTOP")
54+
if stacker.get_estop():
55+
ui.print_error("ESTOP is still pressed, cannot start tests")
56+
return
57+
58+
# TODO: This check should be in the basic axes tests
59+
platform_state = await stacker.get_platform_state()
60+
if platform_state is not PlatformState.UNKNOWN:
61+
ui.print_error("Platform must be removed from the carrier before starting")
62+
ui.get_user_ready("Remove platform from {platform_state.value}")
63+
if await stacker.get_platform_state() is not PlatformState.UNKNOWN:
64+
ui.print_error("Platform is still detected, cannot start tests")
65+
return
66+
67+
device_info = await stacker._driver.get_device_info()
68+
report.set_tag(device_info.sn if device_info.sn else "UNKNOWN")
69+
70+
# RUN TESTS
71+
try:
72+
for section, test_run in cfg.tests.items():
73+
ui.print_title(section.value)
74+
await test_run(stacker, report, section.value)
75+
except Exception as e:
76+
ui.print_error(f"An error occurred: {e}")
77+
78+
# SAVE REPORT
79+
ui.print_title("DONE")
80+
report.save_to_disk()
81+
report.print_results()
82+
83+
# Restart the robot server
84+
if not cfg.simulate:
85+
print("Starting the robot server")
86+
subprocess.run(["systemctl restart opentrons-robot-server &"], shell=True)
87+
88+
89+
if __name__ == "__main__":
90+
parser = argparse.ArgumentParser()
91+
parser.add_argument("--simulate", action="store_true")
92+
# add each test-section as a skippable argument (eg: --skip-connectivity)
93+
for s in TestSection:
94+
parser.add_argument(f"--skip-{s.value.lower()}", action="store_true")
95+
parser.add_argument(f"--only-{s.value.lower()}", action="store_true")
96+
args = parser.parse_args()
97+
_t_sections = {s: f for s, f in TESTS if getattr(args, f"only_{s.value.lower()}")}
98+
if _t_sections:
99+
assert (
100+
len(list(_t_sections.keys())) < 2
101+
), 'use "--only" for just one test, not multiple tests'
102+
else:
103+
_t_sections = {
104+
s: f for s, f in TESTS if not getattr(args, f"skip_{s.value.lower()}")
105+
}
106+
_config = TestConfig(simulate=args.simulate, tests=_t_sections)
107+
asyncio.run(_main(_config))
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
"""Config."""
2+
from dataclasses import dataclass
3+
import enum
4+
from typing import Dict, Callable
5+
6+
from hardware_testing.data.csv_report import CSVReport, CSVSection
7+
8+
from . import (
9+
test_connectivity,
10+
test_z_axis_basic,
11+
test_x_axis_basic,
12+
test_l_axis_basic,
13+
test_z_axis_current_speed,
14+
test_x_axis_current_speed,
15+
test_stallguard,
16+
test_door_switch,
17+
test_estop,
18+
test_ui_leds,
19+
test_uv_lockout_switch,
20+
test_install_detection,
21+
test_tof_basic,
22+
test_tof_functional,
23+
)
24+
25+
26+
class TestSection(enum.Enum):
27+
"""Test Section."""
28+
29+
CONNECTIVITY = "CONNECTIVITY"
30+
DOOR_SWITCH = "DOOR_SWITCH"
31+
ESTOP = "ESTOP"
32+
Z_AXIS_BASIC = "Z_AXIS_BASIC"
33+
L_AXIS_BASIC = "L_AXIS_BASIC"
34+
X_AXIS_BASIC = "X_AXIS_BASIC"
35+
STALLGUARD = "STALLGUARD"
36+
UI_LEDS = "UI_LEDS"
37+
UV_LOCKOUT_SWITCH = "UV_LOCKOUT_SWITCH"
38+
INSTALL_DETECTION = "INSTALL_DETECTION"
39+
TOF_BASIC = "TOF_BASIC"
40+
TOF_FUNCTIONAL = "TOF_FUNCTIONAL"
41+
Z_AXIS_CURRENT_SPEED = "Z_AXIS_CURRENT_SPEED"
42+
X_AXIS_CURRENT_SPEED = "X_AXIS_CURRENT_SPEED"
43+
44+
45+
@dataclass
46+
class TestConfig:
47+
"""Test Config."""
48+
49+
simulate: bool
50+
tests: Dict[TestSection, Callable]
51+
52+
53+
TESTS = [
54+
(
55+
TestSection.CONNECTIVITY,
56+
test_connectivity.run,
57+
),
58+
(
59+
TestSection.Z_AXIS_BASIC,
60+
test_z_axis_basic.run,
61+
),
62+
(
63+
TestSection.X_AXIS_BASIC,
64+
test_x_axis_basic.run,
65+
),
66+
(
67+
TestSection.L_AXIS_BASIC,
68+
test_l_axis_basic.run,
69+
),
70+
(
71+
TestSection.STALLGUARD,
72+
test_stallguard.run,
73+
),
74+
(
75+
TestSection.ESTOP,
76+
test_estop.run,
77+
),
78+
(
79+
TestSection.DOOR_SWITCH,
80+
test_door_switch.run,
81+
),
82+
(
83+
TestSection.UI_LEDS,
84+
test_ui_leds.run,
85+
),
86+
(
87+
TestSection.UV_LOCKOUT_SWITCH,
88+
test_uv_lockout_switch.run,
89+
),
90+
(
91+
TestSection.INSTALL_DETECTION,
92+
test_install_detection.run,
93+
),
94+
(
95+
TestSection.TOF_BASIC,
96+
test_tof_basic.run,
97+
),
98+
(
99+
TestSection.TOF_FUNCTIONAL,
100+
test_tof_functional.run,
101+
),
102+
(
103+
TestSection.Z_AXIS_CURRENT_SPEED,
104+
test_z_axis_current_speed.run,
105+
),
106+
(
107+
TestSection.X_AXIS_CURRENT_SPEED,
108+
test_x_axis_current_speed.run,
109+
),
110+
]
111+
112+
113+
def build_report(test_name: str) -> CSVReport:
114+
"""Build report."""
115+
return CSVReport(
116+
test_name=test_name,
117+
sections=[
118+
CSVSection(
119+
title=TestSection.CONNECTIVITY.value,
120+
lines=test_connectivity.build_csv_lines(),
121+
),
122+
CSVSection(
123+
title=TestSection.ESTOP.value,
124+
lines=test_estop.build_csv_lines(),
125+
),
126+
CSVSection(
127+
title=TestSection.DOOR_SWITCH.value,
128+
lines=test_door_switch.build_csv_lines(),
129+
),
130+
CSVSection(
131+
title=TestSection.Z_AXIS_BASIC.value,
132+
lines=test_z_axis_basic.build_csv_lines(),
133+
),
134+
CSVSection(
135+
title=TestSection.X_AXIS_BASIC.value,
136+
lines=test_x_axis_basic.build_csv_lines(),
137+
),
138+
CSVSection(
139+
title=TestSection.L_AXIS_BASIC.value,
140+
lines=test_l_axis_basic.build_csv_lines(),
141+
),
142+
CSVSection(
143+
title=TestSection.STALLGUARD.value,
144+
lines=test_stallguard.build_csv_lines(),
145+
),
146+
CSVSection(
147+
title=TestSection.UI_LEDS.value,
148+
lines=test_ui_leds.build_csv_lines(),
149+
),
150+
CSVSection(
151+
title=TestSection.UV_LOCKOUT_SWITCH.value,
152+
lines=test_uv_lockout_switch.build_csv_lines(),
153+
),
154+
CSVSection(
155+
title=TestSection.INSTALL_DETECTION.value,
156+
lines=test_install_detection.build_csv_lines(),
157+
),
158+
CSVSection(
159+
title=TestSection.TOF_BASIC.value,
160+
lines=test_tof_basic.build_csv_lines(),
161+
),
162+
CSVSection(
163+
title=TestSection.TOF_FUNCTIONAL.value,
164+
lines=test_tof_functional.build_csv_lines(),
165+
),
166+
CSVSection(
167+
title=TestSection.Z_AXIS_CURRENT_SPEED.value,
168+
lines=test_z_axis_current_speed.build_csv_lines(),
169+
),
170+
CSVSection(
171+
title=TestSection.X_AXIS_CURRENT_SPEED.value,
172+
lines=test_x_axis_current_speed.build_csv_lines(),
173+
),
174+
],
175+
)

0 commit comments

Comments
 (0)