testerkit 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- testerkit/__init__.py +68 -0
- testerkit/_docs/_assets/operator-ui/channels/table.png +0 -0
- testerkit/_docs/_assets/operator-ui/dashboard/runs.png +0 -0
- testerkit/_docs/_assets/operator-ui/dashboard/stations.png +0 -0
- testerkit/_docs/_assets/operator-ui/events/filters.png +0 -0
- testerkit/_docs/_assets/operator-ui/events/table.png +0 -0
- testerkit/_docs/_assets/operator-ui/explore/chart.png +0 -0
- testerkit/_docs/_assets/operator-ui/explore/filters.png +0 -0
- testerkit/_docs/_assets/operator-ui/explore/plot-controls.png +0 -0
- testerkit/_docs/_assets/operator-ui/files/table.png +0 -0
- testerkit/_docs/_assets/operator-ui/launch/form.png +0 -0
- testerkit/_docs/_assets/operator-ui/metrics/filters.png +0 -0
- testerkit/_docs/_assets/operator-ui/metrics/pareto.png +0 -0
- testerkit/_docs/_assets/operator-ui/metrics/ppk.png +0 -0
- testerkit/_docs/_assets/operator-ui/metrics/yield.png +0 -0
- testerkit/_docs/_assets/operator-ui/results/detail-header.png +0 -0
- testerkit/_docs/_assets/operator-ui/results/detail-measurements.png +0 -0
- testerkit/_docs/_assets/operator-ui/results/detail-overview.png +0 -0
- testerkit/_docs/_assets/operator-ui/results/detail-steps.png +0 -0
- testerkit/_docs/_assets/operator-ui/results/stats.png +0 -0
- testerkit/_docs/_assets/operator-ui/results/table.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/designer.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/docs.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/fixtures.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/instruments.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/parts.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/profiles.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/stations.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/tests.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/uuts.png +0 -0
- testerkit/_docs/concepts/configuration/capabilities.md +447 -0
- testerkit/_docs/concepts/configuration/fixtures.md +335 -0
- testerkit/_docs/concepts/configuration/index.md +14 -0
- testerkit/_docs/concepts/configuration/parts.md +276 -0
- testerkit/_docs/concepts/configuration/stations.md +214 -0
- testerkit/_docs/concepts/data/data-stores.md +199 -0
- testerkit/_docs/concepts/data/event-log.md +185 -0
- testerkit/_docs/concepts/data/event-sourcing.md +76 -0
- testerkit/_docs/concepts/data/flight-streaming.md +58 -0
- testerkit/_docs/concepts/data/index.md +17 -0
- testerkit/_docs/concepts/data/sessions.md +78 -0
- testerkit/_docs/concepts/data/three-verbs.md +260 -0
- testerkit/_docs/concepts/execution/index.md +13 -0
- testerkit/_docs/concepts/execution/outcomes.md +199 -0
- testerkit/_docs/concepts/execution/step-hierarchy.md +170 -0
- testerkit/_docs/concepts/execution/step-manifest.md +115 -0
- testerkit/_docs/concepts/index.md +40 -0
- testerkit/_docs/concepts/overview/ai-integration.md +57 -0
- testerkit/_docs/concepts/overview/architecture.md +357 -0
- testerkit/_docs/concepts/overview/index.md +14 -0
- testerkit/_docs/concepts/overview/platform-vs-framework.md +147 -0
- testerkit/_docs/concepts/overview/pytest.md +53 -0
- testerkit/_docs/concepts/overview/tiers.md +46 -0
- testerkit/_docs/how-to/catalog/datasheet-to-test.md +169 -0
- testerkit/_docs/how-to/catalog/index.md +11 -0
- testerkit/_docs/how-to/configuration/configuring-stations.md +364 -0
- testerkit/_docs/how-to/configuration/custom-drivers.md +484 -0
- testerkit/_docs/how-to/configuration/index.md +13 -0
- testerkit/_docs/how-to/configuration/mock-mode.md +342 -0
- testerkit/_docs/how-to/data/benchmarking.md +120 -0
- testerkit/_docs/how-to/data/capture-an-artifact.md +84 -0
- testerkit/_docs/how-to/data/capture-waveform.md +110 -0
- testerkit/_docs/how-to/data/choosing-a-channel-verb.md +108 -0
- testerkit/_docs/how-to/data/compare-runs.md +120 -0
- testerkit/_docs/how-to/data/export-results.md +104 -0
- testerkit/_docs/how-to/data/find-flaky-tests.md +108 -0
- testerkit/_docs/how-to/data/grafana-dashboards.md +148 -0
- testerkit/_docs/how-to/data/index.md +23 -0
- testerkit/_docs/how-to/data/mcp-debug-failures.md +125 -0
- testerkit/_docs/how-to/data/mcp-query-runs.md +120 -0
- testerkit/_docs/how-to/data/querying-channels.md +117 -0
- testerkit/_docs/how-to/data/querying-events.md +85 -0
- testerkit/_docs/how-to/data/stream-live-channel.md +134 -0
- testerkit/_docs/how-to/execution/custom-operator-ui.md +136 -0
- testerkit/_docs/how-to/execution/index.md +21 -0
- testerkit/_docs/how-to/execution/limits.md +193 -0
- testerkit/_docs/how-to/execution/managing-sessions.md +100 -0
- testerkit/_docs/how-to/execution/multi-uut-testing.md +211 -0
- testerkit/_docs/how-to/execution/operator-prompts.md +151 -0
- testerkit/_docs/how-to/execution/profiles.md +304 -0
- testerkit/_docs/how-to/execution/spec-driven-testing.md +169 -0
- testerkit/_docs/how-to/execution/test-context.md +212 -0
- testerkit/_docs/how-to/execution/traceability.md +252 -0
- testerkit/_docs/how-to/execution/vector-expansion.md +394 -0
- testerkit/_docs/how-to/execution/writing-tests.md +363 -0
- testerkit/_docs/how-to/index.md +59 -0
- testerkit/_docs/how-to/overview/index.md +11 -0
- testerkit/_docs/how-to/overview/mcp-integration.md +168 -0
- testerkit/_docs/how-to/overview/operator-ui-tour.md +234 -0
- testerkit/_docs/integration/data/grafana.md +162 -0
- testerkit/_docs/integration/data/index.md +15 -0
- testerkit/_docs/integration/data/lakehouse-import.md +226 -0
- testerkit/_docs/integration/data/logging.md +131 -0
- testerkit/_docs/integration/data/results-api.md +51 -0
- testerkit/_docs/integration/index.md +20 -0
- testerkit/_docs/integration/runtime/harness.md +281 -0
- testerkit/_docs/integration/runtime/index.md +13 -0
- testerkit/_docs/integration/runtime/instruments.md +284 -0
- testerkit/_docs/integration/runtime/pytest-existing.md +315 -0
- testerkit/_docs/reference/catalog/cookbook.md +389 -0
- testerkit/_docs/reference/catalog/index.md +11 -0
- testerkit/_docs/reference/catalog/schema.md +375 -0
- testerkit/_docs/reference/cli.md +660 -0
- testerkit/_docs/reference/configuration.md +406 -0
- testerkit/_docs/reference/data/channels-schema.md +145 -0
- testerkit/_docs/reference/data/event-types.md +554 -0
- testerkit/_docs/reference/data/events-schema.md +120 -0
- testerkit/_docs/reference/data/files-schema.md +141 -0
- testerkit/_docs/reference/data/index.md +18 -0
- testerkit/_docs/reference/data/models.md +2229 -0
- testerkit/_docs/reference/data/outputs.md +82 -0
- testerkit/_docs/reference/data/parquet-schema.md +529 -0
- testerkit/_docs/reference/data/performance-limits.md +224 -0
- testerkit/_docs/reference/data/query-api.md +247 -0
- testerkit/_docs/reference/index.md +69 -0
- testerkit/_docs/reference/operator-ui/channels/detail.md +82 -0
- testerkit/_docs/reference/operator-ui/channels/list.md +70 -0
- testerkit/_docs/reference/operator-ui/dashboard.md +87 -0
- testerkit/_docs/reference/operator-ui/designer.md +167 -0
- testerkit/_docs/reference/operator-ui/events.md +89 -0
- testerkit/_docs/reference/operator-ui/files.md +74 -0
- testerkit/_docs/reference/operator-ui/fixtures.md +100 -0
- testerkit/_docs/reference/operator-ui/instruments.md +126 -0
- testerkit/_docs/reference/operator-ui/launch.md +79 -0
- testerkit/_docs/reference/operator-ui/live.md +102 -0
- testerkit/_docs/reference/operator-ui/measurements.md +159 -0
- testerkit/_docs/reference/operator-ui/metrics.md +217 -0
- testerkit/_docs/reference/operator-ui/parts.md +98 -0
- testerkit/_docs/reference/operator-ui/profiles.md +103 -0
- testerkit/_docs/reference/operator-ui/results/detail.md +214 -0
- testerkit/_docs/reference/operator-ui/results/list.md +106 -0
- testerkit/_docs/reference/operator-ui/stations.md +98 -0
- testerkit/_docs/reference/operator-ui/tests.md +173 -0
- testerkit/_docs/reference/operator-ui/uuts.md +67 -0
- testerkit/_docs/reference/overview/index.md +11 -0
- testerkit/_docs/reference/overview/pytest-native.md +142 -0
- testerkit/_docs/reference/overview/skills.md +177 -0
- testerkit/_docs/reference/pytest/fixtures.md +342 -0
- testerkit/_docs/reference/pytest/index.md +12 -0
- testerkit/_docs/reference/pytest/markers.md +257 -0
- testerkit/_docs/reference/runtime/api.md +246 -0
- testerkit/_docs/reference/runtime/client.md +280 -0
- testerkit/_docs/reference/runtime/connect.md +140 -0
- testerkit/_docs/reference/runtime/index.md +13 -0
- testerkit/_docs/tutorial/01-first-test.md +113 -0
- testerkit/_docs/tutorial/02-mock-instruments.md +88 -0
- testerkit/_docs/tutorial/03-fixtures.md +169 -0
- testerkit/_docs/tutorial/04-limits.md +139 -0
- testerkit/_docs/tutorial/05-configuration.md +194 -0
- testerkit/_docs/tutorial/06-specifications.md +273 -0
- testerkit/_docs/tutorial/07-real-instruments.md +245 -0
- testerkit/_docs/tutorial/08-capabilities.md +223 -0
- testerkit/_docs/tutorial/09-production.md +374 -0
- testerkit/_docs/tutorial/10-live-monitoring.md +156 -0
- testerkit/_docs/tutorial/11-waveforms-and-evidence.md +169 -0
- testerkit/_docs/tutorial/12-continuous-monitoring.md +145 -0
- testerkit/_docs/tutorial/13-parallel-testing.md +233 -0
- testerkit/_docs/tutorial/index.md +61 -0
- testerkit/_docs/tutorial/quickstart.md +282 -0
- testerkit/analysis/__init__.py +9 -0
- testerkit/analysis/_common.py +24 -0
- testerkit/analysis/measurement_facets.py +524 -0
- testerkit/analysis/measurements_query.py +1458 -0
- testerkit/analysis/metrics.py +389 -0
- testerkit/analysis/runs_query.py +434 -0
- testerkit/analysis/steps_query.py +413 -0
- testerkit/api/__init__.py +6 -0
- testerkit/api/_mime.py +71 -0
- testerkit/api/app.py +1171 -0
- testerkit/api/dialogs/__init__.py +36 -0
- testerkit/api/dialogs/manager.py +617 -0
- testerkit/api/dialogs/models.py +79 -0
- testerkit/api/models.py +80 -0
- testerkit/api/responses.py +205 -0
- testerkit/api/runner.py +222 -0
- testerkit/api/schemas.py +311 -0
- testerkit/benchmark/__init__.py +34 -0
- testerkit/benchmark/concurrency.py +248 -0
- testerkit/benchmark/core.py +232 -0
- testerkit/benchmark/runner.py +628 -0
- testerkit/benchmark/scenario.py +313 -0
- testerkit/benchmark/system.py +191 -0
- testerkit/benchmark/workloads.py +507 -0
- testerkit/catalog/__init__.py +6 -0
- testerkit/catalog/generic/generic_dmm.yaml +61 -0
- testerkit/catalog/generic/generic_eload.yaml +31 -0
- testerkit/catalog/generic/generic_fgen.yaml +56 -0
- testerkit/catalog/generic/generic_oscilloscope.yaml +45 -0
- testerkit/catalog/generic/generic_psu.yaml +77 -0
- testerkit/catalog/generic/generic_smu.yaml +73 -0
- testerkit/channels.py +538 -0
- testerkit/cli/__init__.py +32 -0
- testerkit/cli/_common.py +113 -0
- testerkit/cli/_time.py +179 -0
- testerkit/cli/benchmark_cmd.py +56 -0
- testerkit/cli/catalog_cmd.py +39 -0
- testerkit/cli/daemon.py +157 -0
- testerkit/cli/data_cmd.py +1040 -0
- testerkit/cli/discover_cmd.py +94 -0
- testerkit/cli/docs_cmd.py +100 -0
- testerkit/cli/instrument.py +172 -0
- testerkit/cli/mcp_cmd.py +37 -0
- testerkit/cli/metrics.py +366 -0
- testerkit/cli/project.py +312 -0
- testerkit/cli/root.py +14 -0
- testerkit/cli/runs.py +412 -0
- testerkit/cli/schema_cmd.py +87 -0
- testerkit/cli/serve_cmd.py +50 -0
- testerkit/cli/setup_cmd.py +604 -0
- testerkit/cli/station.py +294 -0
- testerkit/cli/validate.py +112 -0
- testerkit/client.py +463 -0
- testerkit/connect.py +635 -0
- testerkit/data/__init__.py +8 -0
- testerkit/data/_accumulator_pool.py +455 -0
- testerkit/data/_atomic.py +59 -0
- testerkit/data/_collection_indices.py +67 -0
- testerkit/data/_daemon_lifecycle.py +535 -0
- testerkit/data/_duckdb_daemon.py +695 -0
- testerkit/data/_duckdb_flight_server.py +813 -0
- testerkit/data/_event_filters.py +15 -0
- testerkit/data/_event_reader.py +101 -0
- testerkit/data/_flight_errors.py +199 -0
- testerkit/data/_flight_query.py +202 -0
- testerkit/data/_flight_retry.py +148 -0
- testerkit/data/_flight_subscribe.py +67 -0
- testerkit/data/_index_epoch.py +342 -0
- testerkit/data/_ipc_writer.py +185 -0
- testerkit/data/_json_safe.py +63 -0
- testerkit/data/_process.py +18 -0
- testerkit/data/_push_relay.py +124 -0
- testerkit/data/_runs_duckdb_daemon.py +2704 -0
- testerkit/data/_session_reaper.py +110 -0
- testerkit/data/_sql_helpers.py +30 -0
- testerkit/data/_store.py +24 -0
- testerkit/data/backends/__init__.py +7 -0
- testerkit/data/backends/_event_accumulator.py +957 -0
- testerkit/data/backends/_row_helpers.py +1172 -0
- testerkit/data/backends/parquet.py +1143 -0
- testerkit/data/backends/protocol.py +35 -0
- testerkit/data/channels/__init__.py +8 -0
- testerkit/data/channels/_flight_daemon.py +75 -0
- testerkit/data/channels/client.py +242 -0
- testerkit/data/channels/flight_manager.py +88 -0
- testerkit/data/channels/index.py +664 -0
- testerkit/data/channels/models.py +418 -0
- testerkit/data/channels/server.py +162 -0
- testerkit/data/channels/store.py +1481 -0
- testerkit/data/data_dir.py +61 -0
- testerkit/data/duckdb_manager.py +79 -0
- testerkit/data/event_log.py +384 -0
- testerkit/data/event_store.py +768 -0
- testerkit/data/events.py +1025 -0
- testerkit/data/exporters/__init__.py +6 -0
- testerkit/data/exporters/_helpers.py +40 -0
- testerkit/data/exporters/csv_exporter.py +168 -0
- testerkit/data/exporters/hdf5.py +234 -0
- testerkit/data/exporters/json_exporter.py +229 -0
- testerkit/data/exporters/mdf4.py +201 -0
- testerkit/data/exporters/stdf.py +255 -0
- testerkit/data/exporters/tdms.py +292 -0
- testerkit/data/files/__init__.py +71 -0
- testerkit/data/files/_backend.py +207 -0
- testerkit/data/files/_catalog_daemon.py +84 -0
- testerkit/data/files/catalog.py +218 -0
- testerkit/data/files/catalog_manager.py +325 -0
- testerkit/data/files/models.py +60 -0
- testerkit/data/files/serializers.py +414 -0
- testerkit/data/files/store.py +463 -0
- testerkit/data/files/streaming.py +783 -0
- testerkit/data/models.py +604 -0
- testerkit/data/ref.py +152 -0
- testerkit/data/retention.py +297 -0
- testerkit/data/run_store.py +367 -0
- testerkit/data/runs_duckdb_manager.py +103 -0
- testerkit/data/schema_dispatch.py +191 -0
- testerkit/data/schema_migrate.py +76 -0
- testerkit/data/schema_versions.py +85 -0
- testerkit/data/schemas.py +288 -0
- testerkit/data/subscribers/__init__.py +48 -0
- testerkit/data/subscribers/_base.py +20 -0
- testerkit/data/subscribers/_output_file.py +25 -0
- testerkit/data/subscribers/replay.py +55 -0
- testerkit/environment.py +84 -0
- testerkit/execution/__init__.py +11 -0
- testerkit/execution/_git.py +190 -0
- testerkit/execution/_state.py +740 -0
- testerkit/execution/accessors.py +54 -0
- testerkit/execution/audit.py +51 -0
- testerkit/execution/cascade.py +85 -0
- testerkit/execution/connections.py +491 -0
- testerkit/execution/harness.py +1931 -0
- testerkit/execution/instrument_events.py +42 -0
- testerkit/execution/limits.py +154 -0
- testerkit/execution/metadata.py +102 -0
- testerkit/execution/mocks.py +63 -0
- testerkit/execution/profiles.py +616 -0
- testerkit/execution/run_scope.py +1331 -0
- testerkit/execution/session_scope.py +196 -0
- testerkit/execution/sidecar.py +280 -0
- testerkit/execution/site_runner.py +705 -0
- testerkit/execution/sites.py +183 -0
- testerkit/execution/sync.py +294 -0
- testerkit/execution/uut_provider.py +231 -0
- testerkit/execution/vectors.py +205 -0
- testerkit/execution/verify.py +396 -0
- testerkit/expand.py +75 -0
- testerkit/files.py +235 -0
- testerkit/fixtures/__init__.py +6 -0
- testerkit/fixtures/manager.py +357 -0
- testerkit/grafana/__init__.py +1 -0
- testerkit/grafana/bootstrap.py +61 -0
- testerkit/grafana/cli.py +314 -0
- testerkit/grafana/dashboards/asset_utilization.json +92 -0
- testerkit/grafana/dashboards/channel_explorer.json +77 -0
- testerkit/grafana/dashboards/event_log.json +92 -0
- testerkit/grafana/dashboards/failure_pareto.json +104 -0
- testerkit/grafana/dashboards/measurement_distribution.json +97 -0
- testerkit/grafana/dashboards/measurement_trend.json +161 -0
- testerkit/grafana/dashboards/station_comparison.json +95 -0
- testerkit/grafana/dashboards/test_duration.json +104 -0
- testerkit/grafana/dashboards/unit_traceability.json +73 -0
- testerkit/grafana/dashboards/yield_overview.json +189 -0
- testerkit/grafana/provisioning/dashboards.yaml.j2 +12 -0
- testerkit/grafana/provisioning/datasources.yaml.j2 +17 -0
- testerkit/grafana/server.py +282 -0
- testerkit/init.py +724 -0
- testerkit/instruments/__init__.py +10 -0
- testerkit/instruments/base.py +82 -0
- testerkit/instruments/discovery/__init__.py +62 -0
- testerkit/instruments/discovery/_base.py +174 -0
- testerkit/instruments/discovery/lxi.py +152 -0
- testerkit/instruments/discovery/ni.py +95 -0
- testerkit/instruments/discovery/serial.py +73 -0
- testerkit/instruments/discovery/visa.py +98 -0
- testerkit/instruments/lifecycle.py +213 -0
- testerkit/instruments/loader.py +79 -0
- testerkit/instruments/locks.py +178 -0
- testerkit/instruments/mocks.py +230 -0
- testerkit/instruments/observer.py +270 -0
- testerkit/instruments/observers/__init__.py +36 -0
- testerkit/instruments/observers/_base.py +68 -0
- testerkit/instruments/observers/daqmx.py +70 -0
- testerkit/instruments/observers/descriptor.py +69 -0
- testerkit/instruments/observers/generic.py +92 -0
- testerkit/instruments/observers/lantz.py +31 -0
- testerkit/instruments/observers/modbus.py +96 -0
- testerkit/instruments/observers/motion.py +68 -0
- testerkit/instruments/observers/ni_modular.py +73 -0
- testerkit/instruments/observers/ophyd.py +80 -0
- testerkit/instruments/observers/pymeasure.py +120 -0
- testerkit/instruments/observers/qcodes.py +66 -0
- testerkit/instruments/observers/scpi.py +88 -0
- testerkit/instruments/observers/tektronix.py +57 -0
- testerkit/instruments/observers/visa.py +103 -0
- testerkit/instruments/pool.py +459 -0
- testerkit/instruments/proxy.py +59 -0
- testerkit/instruments/route_manager.py +329 -0
- testerkit/instruments/routed_proxy.py +88 -0
- testerkit/instruments/server.py +508 -0
- testerkit/instruments/switch.py +43 -0
- testerkit/instruments/visa.py +294 -0
- testerkit/matching/__init__.py +6 -0
- testerkit/matching/service.py +969 -0
- testerkit/mcp/__init__.py +6 -0
- testerkit/mcp/server.py +681 -0
- testerkit/mcp/tools.py +1868 -0
- testerkit/models/__init__.py +18 -0
- testerkit/models/capability.py +598 -0
- testerkit/models/catalog.py +76 -0
- testerkit/models/data_options.py +153 -0
- testerkit/models/enums.py +334 -0
- testerkit/models/instrument.py +152 -0
- testerkit/models/instrument_asset.py +25 -0
- testerkit/models/part.py +271 -0
- testerkit/models/part_manifest.py +96 -0
- testerkit/models/project.py +114 -0
- testerkit/models/station.py +140 -0
- testerkit/models/test_config.py +748 -0
- testerkit/ontology/__init__.py +39 -0
- testerkit/ontology/schema.py +188 -0
- testerkit/ontology/testerkit.yaml +1420 -0
- testerkit/parts/__init__.py +8 -0
- testerkit/parts/context.py +181 -0
- testerkit/parts/folder.py +251 -0
- testerkit/parts/loader.py +27 -0
- testerkit/prompts/__init__.py +17 -0
- testerkit/prompts/core.py +133 -0
- testerkit/pytest_plugin/__init__.py +1287 -0
- testerkit/pytest_plugin/autouse.py +369 -0
- testerkit/pytest_plugin/helpers.py +354 -0
- testerkit/pytest_plugin/hooks.py +1982 -0
- testerkit/pytest_plugin/markers.py +203 -0
- testerkit/pytest_plugin/retry.py +37 -0
- testerkit/pytest_plugin/sweeps.py +117 -0
- testerkit/queries.py +78 -0
- testerkit/reports/__init__.py +6 -0
- testerkit/reports/core.py +492 -0
- testerkit/reports/datasheet.py +831 -0
- testerkit/reports/templates/datasheet.html +383 -0
- testerkit/reports/templates/default.html +153 -0
- testerkit/sbom.py +142 -0
- testerkit/schema_export.py +101 -0
- testerkit/signals.py +63 -0
- testerkit/skills/README.md +58 -0
- testerkit/skills/templates/project-instructions.md +125 -0
- testerkit/skills/testerkit-analysis/SKILL.md +87 -0
- testerkit/skills/testerkit-capture/SKILL.md +114 -0
- testerkit/skills/testerkit-data/SKILL.md +138 -0
- testerkit/skills/testerkit-datasheets/SKILL.md +100 -0
- testerkit/skills/testerkit-datasheets/agents/scaffold-writer.md +115 -0
- testerkit/skills/testerkit-datasheets/agents/section-extractor.md +98 -0
- testerkit/skills/testerkit-datasheets/agents/section-reviewer.md +153 -0
- testerkit/skills/testerkit-datasheets/agents/section-splitter.md +89 -0
- testerkit/skills/testerkit-datasheets/agents/section-writer.md +226 -0
- testerkit/skills/testerkit-datasheets/references/catalog-pipeline.md +271 -0
- testerkit/skills/testerkit-datasheets/references/process-queue.md +42 -0
- testerkit/skills/testerkit-datasheets/references/scaffold.md +156 -0
- testerkit/skills/testerkit-datasheets/references/test-pipeline.md +312 -0
- testerkit/skills/testerkit-debug/SKILL.md +127 -0
- testerkit/skills/testerkit-interactive/SKILL.md +188 -0
- testerkit/skills/testerkit-interactive/references/live-ui-patterns.md +102 -0
- testerkit/skills/testerkit-mocks/SKILL.md +128 -0
- testerkit/skills/testerkit-parts/SKILL.md +126 -0
- testerkit/skills/testerkit-profiles/SKILL.md +139 -0
- testerkit/skills/testerkit-sites/SKILL.md +140 -0
- testerkit/skills/testerkit-stations/SKILL.md +146 -0
- testerkit/skills/testerkit-tests/SKILL.md +136 -0
- testerkit/store.py +1639 -0
- testerkit/ui/__init__.py +71 -0
- testerkit/ui/_asgi.py +162 -0
- testerkit/ui/app.py +32 -0
- testerkit/ui/components/__init__.py +13 -0
- testerkit/ui/components/artifact_viewer.py +250 -0
- testerkit/ui/components/channel_values.py +159 -0
- testerkit/ui/components/event_timeline.py +222 -0
- testerkit/ui/components/execution_gantt.py +210 -0
- testerkit/ui/components/file_streams.py +147 -0
- testerkit/ui/components/instrument_activity.py +146 -0
- testerkit/ui/components/session_table.py +118 -0
- testerkit/ui/pages/__init__.py +25 -0
- testerkit/ui/pages/channels/__init__.py +4 -0
- testerkit/ui/pages/channels/detail.py +932 -0
- testerkit/ui/pages/channels/list.py +515 -0
- testerkit/ui/pages/dashboard.py +236 -0
- testerkit/ui/pages/designer/__init__.py +5 -0
- testerkit/ui/pages/designer/graph.py +635 -0
- testerkit/ui/pages/designer/matching.py +663 -0
- testerkit/ui/pages/designer/page.py +593 -0
- testerkit/ui/pages/designer/properties.py +591 -0
- testerkit/ui/pages/designer/state.py +468 -0
- testerkit/ui/pages/docs/__init__.py +6 -0
- testerkit/ui/pages/docs/index.py +95 -0
- testerkit/ui/pages/docs/page.py +698 -0
- testerkit/ui/pages/events/__init__.py +3 -0
- testerkit/ui/pages/events/list.py +263 -0
- testerkit/ui/pages/explore.py +1108 -0
- testerkit/ui/pages/files/__init__.py +4 -0
- testerkit/ui/pages/files/detail.py +426 -0
- testerkit/ui/pages/files/list.py +447 -0
- testerkit/ui/pages/fixtures/__init__.py +8 -0
- testerkit/ui/pages/fixtures/detail.py +280 -0
- testerkit/ui/pages/fixtures/edit.py +370 -0
- testerkit/ui/pages/fixtures/list.py +180 -0
- testerkit/ui/pages/fixtures/new.py +195 -0
- testerkit/ui/pages/instruments/__init__.py +4 -0
- testerkit/ui/pages/instruments/detail.py +320 -0
- testerkit/ui/pages/instruments/edit.py +482 -0
- testerkit/ui/pages/instruments/list.py +249 -0
- testerkit/ui/pages/instruments/new.py +200 -0
- testerkit/ui/pages/launch.py +261 -0
- testerkit/ui/pages/live.py +124 -0
- testerkit/ui/pages/metrics_page.py +1229 -0
- testerkit/ui/pages/parts/__init__.py +11 -0
- testerkit/ui/pages/parts/detail.py +202 -0
- testerkit/ui/pages/parts/edit.py +310 -0
- testerkit/ui/pages/parts/list.py +160 -0
- testerkit/ui/pages/parts/new.py +170 -0
- testerkit/ui/pages/parts/requirements.py +153 -0
- testerkit/ui/pages/parts/stations.py +199 -0
- testerkit/ui/pages/profiles/__init__.py +4 -0
- testerkit/ui/pages/profiles/detail.py +113 -0
- testerkit/ui/pages/profiles/list.py +86 -0
- testerkit/ui/pages/results/__init__.py +4 -0
- testerkit/ui/pages/results/detail.py +631 -0
- testerkit/ui/pages/results/list.py +230 -0
- testerkit/ui/pages/stations/__init__.py +4 -0
- testerkit/ui/pages/stations/detail.py +256 -0
- testerkit/ui/pages/stations/edit.py +273 -0
- testerkit/ui/pages/stations/list.py +180 -0
- testerkit/ui/pages/stations/new.py +311 -0
- testerkit/ui/pages/tests/__init__.py +4 -0
- testerkit/ui/pages/tests/detail.py +152 -0
- testerkit/ui/pages/tests/list.py +194 -0
- testerkit/ui/pages/uuts/__init__.py +4 -0
- testerkit/ui/pages/uuts/list.py +97 -0
- testerkit/ui/shared/__init__.py +8 -0
- testerkit/ui/shared/components.py +1826 -0
- testerkit/ui/shared/dialogs.py +105 -0
- testerkit/ui/shared/event_binding.py +194 -0
- testerkit/ui/shared/layout.py +314 -0
- testerkit/ui/shared/services.py +1719 -0
- testerkit/ui/shared/timestamps.py +21 -0
- testerkit/ui/static/branding/favicon-16.png +0 -0
- testerkit/ui/static/branding/favicon-32.png +0 -0
- testerkit/ui/static/branding/favicon-48.png +0 -0
- testerkit/ui/static/branding/testerkit-icon-256.png +0 -0
- testerkit/ui/static/branding/testerkit-mark.svg +1 -0
- testerkit/ui/static/branding/testerkit-wordmark.svg +1 -0
- testerkit/ui/static/global.css +465 -0
- testerkit/utils/__init__.py +17 -0
- testerkit/utils/enum_meta.py +800 -0
- testerkit/utils/paths.py +75 -0
- testerkit/utils/ranges.py +257 -0
- testerkit/validation.py +82 -0
- testerkit/verbs.py +142 -0
- testerkit-0.4.0.dist-info/METADATA +250 -0
- testerkit-0.4.0.dist-info/RECORD +521 -0
- testerkit-0.4.0.dist-info/WHEEL +4 -0
- testerkit-0.4.0.dist-info/entry_points.txt +5 -0
- testerkit-0.4.0.dist-info/licenses/LICENSE +191 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Datasheet → tests with Claude Code
|
|
2
|
+
|
|
3
|
+
Walks through the `datasheet-to-test` workflow end-to-end: from a part datasheet PDF to a runnable pytest suite, with operator approval at every step. This flow chains spec extraction, instrument selection, station config, and test scaffolding into one conversation, with an approval gate at each step.
|
|
4
|
+
|
|
5
|
+
For motivation see [why AI integration](../../concepts/overview/ai-integration.md). For the full inventory of what ships, see the [skills reference](../../reference/overview/skills.md).
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- TesterKit installed (`pip install testerkit`)
|
|
10
|
+
- A part datasheet PDF on disk
|
|
11
|
+
- Claude Code installed and authenticated, with access to a high-capability model on your plan (Opus, GPT-5 / o-series, Gemini 2.5 Pro, or equivalent — the workflow does heavy PDF extraction)
|
|
12
|
+
- A working catalog of instruments — either real catalog YAMLs in your project, or you can use TesterKit's bundled generics
|
|
13
|
+
|
|
14
|
+
If you don't have Claude Code, swap to any client that supports MCP — the steps work the same, only the invocation differs (slash command vs conversational). See the [skills reference](../../reference/overview/skills.md#slash-commands) for the matrix.
|
|
15
|
+
|
|
16
|
+
## One-time setup
|
|
17
|
+
|
|
18
|
+
Register TesterKit's MCP server with Claude Code:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
testerkit setup claude-code
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
This does three things ([full reference](../../reference/overview/skills.md#what-the-setup-commands-install)):
|
|
25
|
+
|
|
26
|
+
1. Registers TesterKit as an MCP server (`claude mcp add testerkit -- <testerkit-bin> mcp serve`)
|
|
27
|
+
2. Copies `/catalog-from-datasheet` and `/process-catalog` slash command stubs into `./.claude/commands/`
|
|
28
|
+
3. Writes or merges `./CLAUDE.md` with the TesterKit project instructions
|
|
29
|
+
|
|
30
|
+
Restart Claude Code after `testerkit setup` so it picks up the new server.
|
|
31
|
+
|
|
32
|
+
Confirm MCP registration:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
claude mcp list
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
TesterKit should appear in the list. If it doesn't, re-run `testerkit setup claude-code` and check the printed error.
|
|
39
|
+
|
|
40
|
+
## Invoke the workflow
|
|
41
|
+
|
|
42
|
+
Open Claude Code in your project directory. Start a new conversation with this prompt:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
Run the datasheet-to-test workflow on this datasheet:
|
|
46
|
+
./datasheets/my_part.pdf
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Claude fetches the workflow prompt via MCP (`prompts/get datasheet-to-test`) and begins **Phase 1**.
|
|
50
|
+
|
|
51
|
+
## The phases
|
|
52
|
+
|
|
53
|
+
The workflow STOPS at every gate. You approve, edit, or reject before it moves on.
|
|
54
|
+
|
|
55
|
+
### Phase 1 — Parse datasheet
|
|
56
|
+
|
|
57
|
+
Claude reads the PDF, extracts:
|
|
58
|
+
|
|
59
|
+
- Pin definitions (names, types, signal directions)
|
|
60
|
+
- Electrical characteristics (voltage ranges, current draws, accuracy specs)
|
|
61
|
+
- Test conditions (temperature, supply voltage points)
|
|
62
|
+
|
|
63
|
+
You see a structured summary. Approval gate: "Here's what I extracted, anything missing or wrong?"
|
|
64
|
+
|
|
65
|
+
Common edits at this gate:
|
|
66
|
+
- Renaming pins to match your team's convention
|
|
67
|
+
- Adding characteristics the datasheet implies but doesn't tabulate (e.g., quiescent current at no-load)
|
|
68
|
+
- Removing characteristics you don't intend to test
|
|
69
|
+
|
|
70
|
+
### Phase 2 — Save part spec
|
|
71
|
+
|
|
72
|
+
Claude saves the spec to `parts/<id>.yaml`. The spec uses the same [Capability schema](../../reference/catalog/schema.md) as catalog entries. TesterKit validates the YAML against the catalog schema as it saves; you'll see Claude correct shape errors in-flight if it tries to save something invalid.
|
|
73
|
+
|
|
74
|
+
Approval gate: review the saved YAML. Edit directly if you want — the agent re-reads on the next step.
|
|
75
|
+
|
|
76
|
+
### Phase 2b — Recommend instruments
|
|
77
|
+
|
|
78
|
+
Claude calls `testerkit_match(part_id=<id>)` and proposes instruments that cover the part's specs (see [how capability matching works](../../concepts/overview/ai-integration.md)). Three outcomes:
|
|
79
|
+
|
|
80
|
+
| Outcome | What Claude proposes |
|
|
81
|
+
|---|---|
|
|
82
|
+
| Catalog has matches | Shortlist of matched catalog entries with capability coverage |
|
|
83
|
+
| Catalog is empty / no matches | Asks what equipment you have available |
|
|
84
|
+
| Mixed | Catalog matches for some, asks about gaps |
|
|
85
|
+
|
|
86
|
+
If you have a specific model the catalog doesn't know yet, Claude offers three paths:
|
|
87
|
+
|
|
88
|
+
1. **Fast, approximate:** ask Claude to scaffold a catalog entry from just the model number using its prior knowledge — good for a quick start, not production-accurate.
|
|
89
|
+
2. `generic_dmm` / `generic_psu` / `generic_eload` / `generic_oscilloscope` — bundled with TesterKit, approximate capabilities, fine for mocked development.
|
|
90
|
+
3. **Accurate, for production:** `/catalog-from-datasheet <pdf>` — correct to the datasheet, for catalog entries where spec correctness matters.
|
|
91
|
+
|
|
92
|
+
Pick whichever fits where you are: generics if you're sketching, Claude's prior knowledge for well-known instruments, full datasheet for the production catalog entry.
|
|
93
|
+
|
|
94
|
+
### Phase 3 — Create station config
|
|
95
|
+
|
|
96
|
+
Claude generates `stations/<id>.yaml` wiring the selected instruments to roles (`psu`, `dmm`, `uut_load`, etc.) with realistic mock values. TesterKit validates the wiring when it saves.
|
|
97
|
+
|
|
98
|
+
Approval gate: review the wiring. Most edits here are around VISA resource strings (the agent has no way to discover your bench's actual `TCPIP::*::INSTR` addresses unless you've already populated them or it can call `testerkit_discover` against a live bench).
|
|
99
|
+
|
|
100
|
+
### Phase 4 — Generate tests
|
|
101
|
+
|
|
102
|
+
Two files generated:
|
|
103
|
+
|
|
104
|
+
- `tests/test_<part>.py` — pytest-native test code using the TesterKit fixtures (`context`, `verify`, `measure`, plus instrument role fixtures like `psu`, `dmm`)
|
|
105
|
+
- `tests/test_<part>.yaml` — sidecar YAML with `sweeps:`, `limits:`, `mocks:` for operator-editable values
|
|
106
|
+
|
|
107
|
+
The generated tests use:
|
|
108
|
+
- `verify(name, value)` for judgment-bearing measurements — limits resolve from the active part spec / sidecar / profile, raises on out-of-band
|
|
109
|
+
- `measure(name, value)` for record-only setup readouts
|
|
110
|
+
- `context.changed("vin")` in parametrized sweeps to skip expensive reconfig
|
|
111
|
+
- Native `@pytest.mark.parametrize` for code-owned sweeps; sidecar `sweeps:` for operator-edited sweeps
|
|
112
|
+
|
|
113
|
+
Approval gate: review both files. Edit directly — pytest and the YAML are the source of truth, not Claude's memory of what it generated.
|
|
114
|
+
|
|
115
|
+
### Phase 5 — Execute and analyze
|
|
116
|
+
|
|
117
|
+
Claude calls `testerkit_run(test="tests/test_<id>.py", station="<station_id>", serial="<UUT-SERIAL>", project=<root>)`. The test executes against the configured station (with `mocks:` from the sidecar if `--mock-instruments` is implied, otherwise against the real bench).
|
|
118
|
+
|
|
119
|
+
Claude shows you the results table — rows are measurements, columns are sweep axes, cells colored pass/fail/skip. From here you can ask follow-ups:
|
|
120
|
+
|
|
121
|
+
- "Why did the load=0.8 row fail at vin=4.5?" → Claude pulls the measurement detail via `testerkit_runs` + `testerkit_steps`
|
|
122
|
+
- "Open this run in the browser" → `testerkit_open(type="run", id=<run-id>)` returns a `testerkit serve` URL
|
|
123
|
+
- "Tighten the output_voltage tolerance to ±1%" → Claude edits the sidecar and re-runs
|
|
124
|
+
|
|
125
|
+
## What's actually saved to your project
|
|
126
|
+
|
|
127
|
+
After the workflow completes, your project tree has:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
my_project/
|
|
131
|
+
├── testerkit.yaml # set by testerkit_project init
|
|
132
|
+
├── parts/
|
|
133
|
+
│ └── <id>.yaml # phase 2
|
|
134
|
+
├── stations/
|
|
135
|
+
│ └── <station_id>.yaml # phase 3
|
|
136
|
+
├── tests/
|
|
137
|
+
│ ├── test_<part>.py # phase 4
|
|
138
|
+
│ └── test_<part>.yaml # phase 4 sidecar
|
|
139
|
+
└── catalog/ # only if Phase 2b added an instrument entry
|
|
140
|
+
└── <instrument>.yaml
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Every file is plain YAML or Python. Git diffs work. Code review works. If you want to delete the AI from the loop, `pytest tests/` still runs the test.
|
|
144
|
+
|
|
145
|
+
## When things go wrong
|
|
146
|
+
|
|
147
|
+
| Symptom | Cause | Fix |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| Claude can't find the workflow | MCP server not registered or Claude not restarted after `testerkit setup` | `claude mcp list` to verify; restart Claude Code |
|
|
150
|
+
| Agent loops trying to save an invalid YAML | The save was rejected because the YAML didn't match the catalog schema | Let it iterate — validation is the feedback signal; or stop it and edit the YAML by hand |
|
|
151
|
+
| Test runs but every row is `SKIP` / `MISSING_LIMIT` | Phase 4 generated `verify()` calls without limits, and no sidecar / part spec covers them | Either add limits to the sidecar `limits:` block or switch the calls to `measure()` for characterization-only |
|
|
152
|
+
| Instrument match returns nothing | Catalog is empty or capability requirements aren't covered | Use generics for development, or run `/catalog-from-datasheet` for the missing instruments |
|
|
153
|
+
| Agent picks the wrong instrument | The capability match is correct but the agent's preference doesn't match yours | Tell it directly: "I want the Keithley 2400 for the load instead of the eload" — it'll update the station and re-validate |
|
|
154
|
+
|
|
155
|
+
## Variations
|
|
156
|
+
|
|
157
|
+
Three ways to use this flow short of the full pipeline:
|
|
158
|
+
|
|
159
|
+
1. **Just part spec.** Stop after Phase 2. You get a part YAML; do station + tests by hand.
|
|
160
|
+
2. **Part + tests, mock instruments.** Stop after Phase 4, use the bundled `generic_*` instruments through Phase 2b, run `pytest --mock-instruments`. No real hardware needed; useful for test-code review before the bench is ready.
|
|
161
|
+
3. **Incremental update.** Re-invoke the workflow on a part that already has files. The agent reads the existing YAMLs and proposes diffs rather than from-scratch generation.
|
|
162
|
+
|
|
163
|
+
## See also
|
|
164
|
+
|
|
165
|
+
- [Concepts: why AI integration](../../concepts/overview/ai-integration.md) — motivation
|
|
166
|
+
- [Reference: skills](../../reference/overview/skills.md) — full inventory of workflows, agents, MCP tools
|
|
167
|
+
- [How-to: MCP integration](../overview/mcp-integration.md) — per-client setup detail
|
|
168
|
+
- [Reference: catalog schema](../../reference/catalog/schema.md) — the shape part spec and catalog entries share
|
|
169
|
+
- [Tutorial step 3: pytest-native tests](../../tutorial/03-fixtures.md) — what the generated test code looks like in context
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# How-To — Catalog
|
|
2
|
+
|
|
3
|
+
AI-assisted authoring against the capability catalog: produce instrument YAML and part YAML from a datasheet PDF with operator approval at every step.
|
|
4
|
+
|
|
5
|
+
- [Datasheet → tests with Claude Code](datasheet-to-test.md) — end-to-end walkthrough of the `datasheet-to-test` workflow
|
|
6
|
+
|
|
7
|
+
## See also
|
|
8
|
+
|
|
9
|
+
- [Concepts → AI integration](../../concepts/overview/ai-integration.md) — what the MCP surface gives an AI client and where the boundary sits
|
|
10
|
+
- [Reference → Catalog schema](../../reference/catalog/schema.md) and [Catalog cookbook](../../reference/catalog/cookbook.md) — the YAML shape the workflow produces
|
|
11
|
+
- [Reference → Skills](../../reference/overview/skills.md) — full inventory of workflows, sub-agents, slash commands the platform ships
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
# Configuring Stations
|
|
2
|
+
|
|
3
|
+
This guide covers station configuration for different environments.
|
|
4
|
+
|
|
5
|
+
## Basic Station Config
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
# stations/bench_1.yaml
|
|
9
|
+
id: bench_1
|
|
10
|
+
name: "Production Bench 1"
|
|
11
|
+
location: "Lab A"
|
|
12
|
+
|
|
13
|
+
instruments:
|
|
14
|
+
dmm:
|
|
15
|
+
type: dmm
|
|
16
|
+
driver: pymeasure.instruments.keysight.Keysight34461A
|
|
17
|
+
resource: "TCPIP::192.168.1.100::INSTR"
|
|
18
|
+
psu:
|
|
19
|
+
type: psu
|
|
20
|
+
driver: pymeasure.instruments.keysight.KeysightE36312A
|
|
21
|
+
resource: "GPIB0::5::INSTR"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Station Fields
|
|
25
|
+
|
|
26
|
+
| Field | Required | Description |
|
|
27
|
+
|-------|----------|-------------|
|
|
28
|
+
| `id` | Defaults to filename stem | Unique identifier — must match the filename stem if declared explicitly |
|
|
29
|
+
| `name` | Yes | Display name |
|
|
30
|
+
| `location` | No | Physical location |
|
|
31
|
+
| `description` | No | Description |
|
|
32
|
+
| `supported_phases` | No | Documents which phases this bench is set up for — shown in the stations UI |
|
|
33
|
+
|
|
34
|
+
## Instrument Fields
|
|
35
|
+
|
|
36
|
+
Per [`StationInstrumentConfig`](../../reference/data/models.md):
|
|
37
|
+
|
|
38
|
+
| Field | Required | Description |
|
|
39
|
+
|-------|----------|-------------|
|
|
40
|
+
| `type` | Yes | Instrument type (dmm, psu, etc.) |
|
|
41
|
+
| `driver` | At least one of driver/resource (unless `mock: true`) | The driver to load, written `package.module.DriverName` (e.g. `pymeasure.instruments.keysight.Keysight34461A`) |
|
|
42
|
+
| `resource` | At least one of driver/resource (unless `mock: true`) | VISA address or connection string |
|
|
43
|
+
| `catalog_ref` | No | ID of a catalog entry that declares this instrument's capabilities |
|
|
44
|
+
| `channels` | No | Named channel aliases (`dict[str, str]`) |
|
|
45
|
+
| `description` | No | Human-readable description |
|
|
46
|
+
| `mock` | No | Always mock this instrument (even without `--mock-instruments`). Default `false` |
|
|
47
|
+
| `mock_config` | No | Return values when running in mock mode |
|
|
48
|
+
|
|
49
|
+
## Using a station's instruments in a test
|
|
50
|
+
|
|
51
|
+
Each role under `instruments:` becomes a pytest fixture of the same name. A `dmm:` role gives you a `dmm` fixture; `psu:` gives `psu`. Rename the role, rename the fixture.
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
def test_rail_voltage(dmm, psu):
|
|
55
|
+
psu.voltage = 5.0
|
|
56
|
+
reading = dmm.measure_dc_voltage()
|
|
57
|
+
assert 3.2 < reading < 3.4
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The fixtures are session-scoped — TesterKit connects each instrument once and shares the driver instance across all tests in the run.
|
|
61
|
+
|
|
62
|
+
## VISA Addresses
|
|
63
|
+
|
|
64
|
+
### TCP/IP (LAN)
|
|
65
|
+
|
|
66
|
+
```yaml
|
|
67
|
+
resource: "TCPIP::192.168.1.100::INSTR"
|
|
68
|
+
resource: "TCPIP::192.168.1.100::5025::SOCKET" # With port
|
|
69
|
+
resource: "TCPIP::dmm.lab.local::INSTR" # DNS name
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### GPIB
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
resource: "GPIB0::5::INSTR" # Board 0, address 5
|
|
76
|
+
resource: "GPIB1::12::INSTR" # Board 1, address 12
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### USB
|
|
80
|
+
|
|
81
|
+
```yaml
|
|
82
|
+
resource: "USB0::0x2A8D::0x0101::MY12345::INSTR"
|
|
83
|
+
# Format: USB{board}::{vendor}::{part}::{serial}::INSTR
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Serial
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
resource: "ASRL/dev/ttyUSB0::INSTR" # Linux
|
|
90
|
+
resource: "ASRLCOM3::INSTR" # Windows
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Mock Mode Configuration
|
|
94
|
+
|
|
95
|
+
Configure default values for `--mock-instruments` mode:
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
instruments:
|
|
99
|
+
dmm:
|
|
100
|
+
type: dmm
|
|
101
|
+
driver: pymeasure.instruments.keysight.Keysight34461A
|
|
102
|
+
resource: "TCPIP::192.168.1.100::INSTR"
|
|
103
|
+
mock_config:
|
|
104
|
+
measure_dc_voltage: 3.31
|
|
105
|
+
measure_current: 0.1
|
|
106
|
+
measure_resistance: 1000
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Running in Mock Mode
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
pytest tests/ --station=stations/bench_1.yaml --mock-instruments --uut-serial=SIM001
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The `--mock-instruments` flag uses mock instruments instead of real hardware. Mock values come from `mock_config` in the station, or can be overridden per-test in the sidecar YAML next to your test file (`tests/test_*.yaml`).
|
|
116
|
+
|
|
117
|
+
## Station Types
|
|
118
|
+
|
|
119
|
+
A station type is a template — one YAML file per type under `stations/types/<id>.yaml`. It declares the instrument roles (and their `type:` and `driver:`) every station of that type must provide, plus the catalog capability ids the type advertises:
|
|
120
|
+
|
|
121
|
+
```yaml
|
|
122
|
+
# stations/types/voltage_tester.yaml
|
|
123
|
+
id: voltage_tester
|
|
124
|
+
description: "Basic voltage testing station"
|
|
125
|
+
instruments:
|
|
126
|
+
dmm:
|
|
127
|
+
type: dmm
|
|
128
|
+
driver: pymeasure.instruments.keysight.Keysight34461A
|
|
129
|
+
psu:
|
|
130
|
+
type: psu
|
|
131
|
+
driver: pymeasure.instruments.keysight.KeysightE36312A
|
|
132
|
+
capabilities:
|
|
133
|
+
- keysight.34461a.dc_voltage
|
|
134
|
+
- keysight.e36312a.dc_source
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```yaml
|
|
138
|
+
# stations/types/full_test.yaml
|
|
139
|
+
id: full_test
|
|
140
|
+
description: "Complete test station"
|
|
141
|
+
instruments:
|
|
142
|
+
dmm:
|
|
143
|
+
type: dmm
|
|
144
|
+
driver: pymeasure.instruments.keysight.Keysight34461A
|
|
145
|
+
psu:
|
|
146
|
+
type: psu
|
|
147
|
+
driver: pymeasure.instruments.keysight.KeysightE36312A
|
|
148
|
+
scope:
|
|
149
|
+
type: scope
|
|
150
|
+
driver: drivers.scope.MyScope
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
There is no `required:` field on an instrument entry — every role listed under `instruments:` is required, and any role not listed is omitted by definition. `capabilities:` is a list of catalog capability ids (strings), not inline capability dicts.
|
|
154
|
+
|
|
155
|
+
Reference in station instances:
|
|
156
|
+
|
|
157
|
+
```yaml
|
|
158
|
+
# stations/bench_1.yaml
|
|
159
|
+
id: bench_1
|
|
160
|
+
name: "Production Bench 1"
|
|
161
|
+
station_type: voltage_tester
|
|
162
|
+
location: "Lab A"
|
|
163
|
+
|
|
164
|
+
instruments:
|
|
165
|
+
dmm:
|
|
166
|
+
type: dmm
|
|
167
|
+
driver: pymeasure.instruments.keysight.Keysight34461A
|
|
168
|
+
resource: "TCPIP::192.168.1.100::INSTR"
|
|
169
|
+
psu:
|
|
170
|
+
type: psu
|
|
171
|
+
driver: pymeasure.instruments.keysight.KeysightE36312A
|
|
172
|
+
resource: "GPIB0::5::INSTR"
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Multiple Stations
|
|
176
|
+
|
|
177
|
+
### Production Lab
|
|
178
|
+
|
|
179
|
+
```yaml
|
|
180
|
+
# stations/prod_bench_1.yaml
|
|
181
|
+
id: prod_bench_1
|
|
182
|
+
name: "Production Bench 1"
|
|
183
|
+
location: "Production Floor, Bay 1"
|
|
184
|
+
|
|
185
|
+
supported_phases:
|
|
186
|
+
- production
|
|
187
|
+
|
|
188
|
+
instruments:
|
|
189
|
+
dmm:
|
|
190
|
+
type: dmm
|
|
191
|
+
driver: pymeasure.instruments.keysight.Keysight34461A
|
|
192
|
+
resource: "TCPIP::192.168.10.101::INSTR"
|
|
193
|
+
psu:
|
|
194
|
+
type: psu
|
|
195
|
+
driver: pymeasure.instruments.keysight.KeysightE36312A
|
|
196
|
+
resource: "TCPIP::192.168.10.102::INSTR"
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Development Lab
|
|
200
|
+
|
|
201
|
+
```yaml
|
|
202
|
+
# stations/dev_bench.yaml
|
|
203
|
+
id: dev_bench
|
|
204
|
+
name: "Development Bench"
|
|
205
|
+
location: "R&D Lab"
|
|
206
|
+
|
|
207
|
+
supported_phases:
|
|
208
|
+
- development
|
|
209
|
+
- debug
|
|
210
|
+
|
|
211
|
+
instruments:
|
|
212
|
+
dmm:
|
|
213
|
+
type: dmm
|
|
214
|
+
driver: pymeasure.instruments.keysight.Keysight34461A
|
|
215
|
+
resource: "USB0::0x2A8D::0x0101::MY12345::INSTR"
|
|
216
|
+
psu:
|
|
217
|
+
type: psu
|
|
218
|
+
driver: pymeasure.instruments.keysight.KeysightE36312A
|
|
219
|
+
resource: "GPIB0::5::INSTR"
|
|
220
|
+
scope:
|
|
221
|
+
type: scope
|
|
222
|
+
driver: drivers.scope.MyScope
|
|
223
|
+
resource: "TCPIP::192.168.1.200::INSTR"
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### CI/CD
|
|
227
|
+
|
|
228
|
+
```yaml
|
|
229
|
+
# stations/ci_station.yaml
|
|
230
|
+
id: ci_station
|
|
231
|
+
name: "CI Environment"
|
|
232
|
+
description: "For automated testing with --mock-instruments"
|
|
233
|
+
|
|
234
|
+
instruments:
|
|
235
|
+
dmm:
|
|
236
|
+
type: dmm
|
|
237
|
+
mock: true
|
|
238
|
+
catalog_ref: generic_dmm
|
|
239
|
+
mock_config:
|
|
240
|
+
measure_dc_voltage: 3.31
|
|
241
|
+
measure_current: 0.1
|
|
242
|
+
psu:
|
|
243
|
+
type: psu
|
|
244
|
+
mock: true
|
|
245
|
+
catalog_ref: generic_psu
|
|
246
|
+
mock_config:
|
|
247
|
+
measure_voltage: 5.0
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Run in CI:
|
|
251
|
+
```bash
|
|
252
|
+
pytest tests/ --station=stations/ci_station.yaml --mock-instruments --uut-serial=CI-TEST
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Selecting a fixture at run time
|
|
256
|
+
|
|
257
|
+
Stations don't pin a fixture themselves. The active fixture is selected by `--fixture=...` on the pytest command line (or by a profile that sets it). The plugin validates that the fixture's `part_id` / `part_family` matches the active part spec before any test runs.
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
pytest tests/ \
|
|
261
|
+
--station=bench_1 \
|
|
262
|
+
--fixture=fixtures/power_board_fixture.yaml \
|
|
263
|
+
--uut-serial=SN001
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
See [Fixtures](../../concepts/configuration/fixtures.md) for the pin-to-instrument mapping model.
|
|
267
|
+
|
|
268
|
+
## Capability Declarations
|
|
269
|
+
|
|
270
|
+
A station instance (`stations/<id>.yaml`) does not carry a `capabilities:` field — capabilities are derived from each instrument's catalog entry when the station loads. See [Capabilities](../../concepts/configuration/capabilities.md) for how capability matching works.
|
|
271
|
+
|
|
272
|
+
If you want to advertise a fixed capability set as part of a *type* (so concrete stations of that type are guaranteed to provide it), declare it on the **station type**, not on the instance, as a list of catalog capability ids:
|
|
273
|
+
|
|
274
|
+
```yaml
|
|
275
|
+
# stations/types/voltage_bench.yaml
|
|
276
|
+
id: voltage_bench
|
|
277
|
+
description: "Generic DC + AC voltage bench"
|
|
278
|
+
instruments:
|
|
279
|
+
dmm:
|
|
280
|
+
type: dmm
|
|
281
|
+
driver: pymeasure.instruments.keysight.Keysight34461A
|
|
282
|
+
psu:
|
|
283
|
+
type: psu
|
|
284
|
+
driver: pymeasure.instruments.keysight.KeysightE36312A
|
|
285
|
+
capabilities:
|
|
286
|
+
- keysight.34461a.dc_voltage
|
|
287
|
+
- keysight.34461a.ac_voltage
|
|
288
|
+
- keysight.e36312a.dc_source
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
To customize the capabilities a specific instrument provides, edit that instrument's catalog YAML (`catalog/<vendor>/<model>.yaml`) — not the station file.
|
|
292
|
+
|
|
293
|
+
## Validation
|
|
294
|
+
|
|
295
|
+
To validate a station file before a run, point pytest at it — a bad config fails fast:
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
pytest --collect-only --station=stations/bench_1.yaml
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
A missing required field or a type mismatch raises a `pydantic.ValidationError` before any test is collected.
|
|
302
|
+
|
|
303
|
+
## Shared Instruments (Multi-UUT)
|
|
304
|
+
|
|
305
|
+
When a multi-UUT fixture runs sites in parallel and more than one site uses the same instrument role, TesterKit connects that instrument once and shares it across sites — no extra config. See [Multi-UUT testing](../execution/multi-uut-testing.md).
|
|
306
|
+
|
|
307
|
+
## Best Practices
|
|
308
|
+
|
|
309
|
+
1. **Use descriptive station IDs** — `prod_bench_1` not `station1`
|
|
310
|
+
2. **Include location** — Helps operators find equipment
|
|
311
|
+
3. **Document supported phases** — `supported_phases:` records which phases this bench is set up for; it is shown in the stations UI
|
|
312
|
+
4. **Create a CI station** — Fully mocked for automated tests; keep one `stations/ci_station.yaml` with `mock: true` on every instrument
|
|
313
|
+
5. **Version control** — Track station YAML changes alongside test code
|
|
314
|
+
|
|
315
|
+
## Common Configurations
|
|
316
|
+
|
|
317
|
+
### Single DMM
|
|
318
|
+
|
|
319
|
+
```yaml
|
|
320
|
+
id: simple_station
|
|
321
|
+
name: "Simple DMM Station"
|
|
322
|
+
|
|
323
|
+
instruments:
|
|
324
|
+
dmm:
|
|
325
|
+
type: dmm
|
|
326
|
+
driver: pymeasure.instruments.keysight.Keysight34461A
|
|
327
|
+
resource: "USB0::0x2A8D::0x0101::MY12345::INSTR"
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Full Production
|
|
331
|
+
|
|
332
|
+
```yaml
|
|
333
|
+
id: production_station
|
|
334
|
+
name: "Production Station"
|
|
335
|
+
location: "Production Floor"
|
|
336
|
+
|
|
337
|
+
instruments:
|
|
338
|
+
dmm_1:
|
|
339
|
+
type: dmm
|
|
340
|
+
driver: pymeasure.instruments.keysight.Keysight34461A
|
|
341
|
+
resource: "TCPIP::192.168.1.101::INSTR"
|
|
342
|
+
dmm_2:
|
|
343
|
+
type: dmm
|
|
344
|
+
driver: pymeasure.instruments.keysight.Keysight34461A
|
|
345
|
+
resource: "TCPIP::192.168.1.102::INSTR"
|
|
346
|
+
psu:
|
|
347
|
+
type: psu
|
|
348
|
+
driver: pymeasure.instruments.keysight.KeysightE36312A
|
|
349
|
+
resource: "TCPIP::192.168.1.103::INSTR"
|
|
350
|
+
eload:
|
|
351
|
+
type: eload
|
|
352
|
+
driver: drivers.eload.MyELoad
|
|
353
|
+
resource: "TCPIP::192.168.1.104::INSTR"
|
|
354
|
+
scope:
|
|
355
|
+
type: scope
|
|
356
|
+
driver: drivers.scope.MyScope
|
|
357
|
+
resource: "TCPIP::192.168.1.105::INSTR"
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Next Steps
|
|
361
|
+
|
|
362
|
+
- [Stations Concept](../../concepts/configuration/stations.md) — Understanding stations
|
|
363
|
+
- [Capabilities](../../concepts/configuration/capabilities.md) — Capability matching
|
|
364
|
+
- [Custom drivers](custom-drivers.md) — Build a non-VISA driver
|