简化 Autocal 界面测试并减少等待开销
用轻量曲面和独立页面验证普通交互,收拢窗口清理,并让后台测试任务获得执行时间。保留原有 90 项用例,113 项相关测试及代码检查通过。
This commit is contained in:
@@ -2,11 +2,13 @@
|
||||
|
||||
import time
|
||||
|
||||
from PySide6.QtTest import QTest
|
||||
from PySide6.QtCore import QCoreApplication
|
||||
|
||||
|
||||
def wait_review(widget):
|
||||
deadline = time.monotonic() + 10
|
||||
while widget._job is not None and time.monotonic() < deadline:
|
||||
QTest.qWait(10)
|
||||
QCoreApplication.processEvents()
|
||||
# Release the GIL so the Python recording worker can finish its I/O.
|
||||
time.sleep(.001)
|
||||
assert widget._job is None, "background review did not finish"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,22 @@ from orisys_autocal.record_overview import load_overview, overview_rows, read_pl
|
||||
from orisys_autocal.session_review import review_session
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def overview_dialog(qt_app):
|
||||
"""Keep chart ownership local to the tests that exercise the overview UI."""
|
||||
from orisys_autocal.ui.record_overview_dialog import RecordOverviewDialog
|
||||
|
||||
dialogs = []
|
||||
def create(directory, **kwargs):
|
||||
dialog = RecordOverviewDialog(directory, **kwargs)
|
||||
dialogs.append(dialog)
|
||||
return dialog
|
||||
yield create
|
||||
for dialog in reversed(dialogs):
|
||||
dialog.close()
|
||||
dialog.deleteLater()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def overview_session(repeated_session):
|
||||
root, selections = repeated_session
|
||||
@@ -105,14 +121,13 @@ def test_overview_requires_all_planned_hold_windows_for_reviewed_status(overview
|
||||
assert overview_rows(review)[0]["status"] == "reviewed"
|
||||
|
||||
|
||||
def test_overview_gui_plan_click_trial_filter_and_saved_roundtrip(qt_app, overview_session, monkeypatch, tmp_path):
|
||||
def test_overview_gui_plan_click_trial_filter_and_saved_roundtrip(qt_app, overview_session, monkeypatch, tmp_path, overview_dialog):
|
||||
from orisys_autocal.ui import record_overview_dialog
|
||||
from orisys_autocal.ui.session_review_dialog import SessionReviewDialog
|
||||
|
||||
root, selections, plan_path = overview_session
|
||||
dialog = record_overview_dialog.RecordOverviewDialog(root)
|
||||
dialog.review = review_session(root, selections=selections)
|
||||
dialog._refresh()
|
||||
dialog = overview_dialog(
|
||||
root, review=review_session(root, selections=selections))
|
||||
monkeypatch.setattr(record_overview_dialog.QFileDialog, "getOpenFileName", lambda *args: (str(plan_path), ""))
|
||||
dialog.findChild(QAction, "overview_import_plan").trigger()
|
||||
assert dialog.table.rowCount() == 4
|
||||
@@ -165,7 +180,6 @@ def test_overview_gui_plan_click_trial_filter_and_saved_roundtrip(qt_app, overvi
|
||||
dialog.findChild(QAction, "overview_load").trigger()
|
||||
wait_review(dialog)
|
||||
assert dialog.table.rowCount() == 4
|
||||
dialog.close()
|
||||
|
||||
|
||||
def test_calibration_review_action_opens_records_tab(make_window, overview_session, monkeypatch):
|
||||
@@ -184,16 +198,17 @@ def test_calibration_review_action_opens_records_tab(make_window, overview_sessi
|
||||
window.close()
|
||||
|
||||
|
||||
def test_records_tab_browse_error_and_reload(make_window, overview_session, monkeypatch, qt_app, tmp_path):
|
||||
def test_records_tab_browse_error_and_reload(overview_session, monkeypatch, qt_app, tmp_path):
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtTest import QTest
|
||||
from orisys_autocal.ui.record_overview_dialog import QFileDialog
|
||||
from PySide6.QtWidgets import QVBoxLayout, QWidget
|
||||
from orisys_autocal.ui.record_overview_dialog import QFileDialog, RecordOverviewPage
|
||||
|
||||
root, _, _ = overview_session
|
||||
window = make_window()
|
||||
window = QWidget()
|
||||
window.resize(1600, 1000)
|
||||
window.workspace.set_current_key("records")
|
||||
page = window.workspace.page("records")
|
||||
page = RecordOverviewPage(window)
|
||||
QVBoxLayout(window).addWidget(page)
|
||||
assert page.overview is None and page.path_label.text()
|
||||
monkeypatch.setattr(QFileDialog, "getExistingDirectory", lambda *args: str(root))
|
||||
page.open_button.click()
|
||||
@@ -217,10 +232,10 @@ def test_records_tab_browse_error_and_reload(make_window, overview_session, monk
|
||||
assert page.overview.save_button.isVisible()
|
||||
assert window.grab().save(str(tmp_path / "records-tab-small.png"))
|
||||
window.close()
|
||||
window.deleteLater()
|
||||
|
||||
|
||||
def test_operator_outline_identity_incomplete_inspection_and_equal_scale(qt_app, overview_session, tmp_path):
|
||||
from orisys_autocal.ui.record_overview_dialog import RecordOverviewDialog
|
||||
def test_operator_outline_identity_incomplete_inspection_and_equal_scale(qt_app, overview_session, tmp_path, overview_dialog):
|
||||
from PySide6.QtCore import Qt
|
||||
|
||||
root, _, _ = overview_session
|
||||
@@ -232,7 +247,7 @@ def test_operator_outline_identity_incomplete_inspection_and_equal_scale(qt_app,
|
||||
}
|
||||
manifest["trials"][0].update(status="incomplete", reason="operator stopped")
|
||||
write_json(root / "session.json", manifest)
|
||||
dialog = RecordOverviewDialog(root)
|
||||
dialog = overview_dialog(root)
|
||||
assert "F-TEST" in dialog.identity.text() and "finger" in dialog.identity.text()
|
||||
assert dialog.outline_state == "snapshot"
|
||||
assert dialog.trials.currentData() == "trial-001"
|
||||
@@ -250,4 +265,3 @@ def test_operator_outline_identity_incomplete_inspection_and_equal_scale(qt_app,
|
||||
assert (x.max() - x.min()) / area.width() == pytest.approx((y.max() - y.min()) / area.height(), rel=.02)
|
||||
assert len(dialog.uv_chart.series()) == 5
|
||||
assert dialog.grab().save(str(tmp_path / "operator-incomplete.png"))
|
||||
dialog.close()
|
||||
|
||||
@@ -19,6 +19,22 @@ def _csv(path, rows):
|
||||
writer.writerows(rows)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def review_dialog(qt_app):
|
||||
"""Give each test fresh dialogs and release their chart trees afterwards."""
|
||||
from orisys_autocal.ui.session_review_dialog import SessionReviewDialog
|
||||
|
||||
dialogs = []
|
||||
def create(directory, **kwargs):
|
||||
dialog = SessionReviewDialog(directory, **kwargs)
|
||||
dialogs.append(dialog)
|
||||
return dialog
|
||||
yield create
|
||||
for dialog in reversed(dialogs):
|
||||
dialog.close()
|
||||
dialog.deleteLater()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def session(tmp_path):
|
||||
manifest = {
|
||||
@@ -106,10 +122,8 @@ def test_review_refuses_mismatched_identity_and_paths_outside_session(session):
|
||||
review_session(session)
|
||||
|
||||
|
||||
def test_review_dialog_shows_saved_windows_charts_and_new_export(qt_app, session, tmp_path):
|
||||
from orisys_autocal.ui.session_review_dialog import SessionReviewDialog
|
||||
|
||||
dialog = SessionReviewDialog(session)
|
||||
def test_review_dialog_shows_saved_windows_charts_and_new_export(qt_app, session, tmp_path, review_dialog):
|
||||
dialog = review_dialog(session)
|
||||
assert dialog.sites.count() == 2
|
||||
assert dialog.table.rowCount() == 5
|
||||
assert dialog.pages.currentIndex() == 0 and dialog.pages.count() == 2
|
||||
@@ -127,7 +141,6 @@ def test_review_dialog_shows_saved_windows_charts_and_new_export(qt_app, session
|
||||
dialog.show()
|
||||
qt_app.processEvents()
|
||||
assert dialog.grab().save(str(tmp_path / "review.png"))
|
||||
dialog.close()
|
||||
|
||||
|
||||
def test_reviewed_windows_roundtrip_and_reject_changed_inputs(session):
|
||||
@@ -168,10 +181,10 @@ def test_invalid_review_selection_does_not_become_verified(session):
|
||||
}})
|
||||
|
||||
|
||||
def test_operator_confirms_windows_in_dialog_and_reloads_them(qt_app, session, monkeypatch):
|
||||
def test_operator_confirms_windows_in_dialog_and_reloads_them(session, monkeypatch, review_dialog):
|
||||
from orisys_autocal.ui import session_review_dialog
|
||||
|
||||
dialog = session_review_dialog.SessionReviewDialog(session)
|
||||
dialog = review_dialog(session)
|
||||
for row in (0, 1):
|
||||
dialog.table.selectRow(row)
|
||||
dialog.end_s.setValue(2)
|
||||
@@ -182,14 +195,12 @@ def test_operator_confirms_windows_in_dialog_and_reloads_them(qt_app, session, m
|
||||
dialog.save_button.click()
|
||||
wait_review(dialog)
|
||||
saved = next(session.glob("derived/*/review.json"))
|
||||
fresh = session_review_dialog.SessionReviewDialog(session)
|
||||
fresh = review_dialog(session)
|
||||
monkeypatch.setattr(session_review_dialog.QFileDialog, "getOpenFileName",
|
||||
lambda *args: (str(saved), ""))
|
||||
fresh.load_button.click()
|
||||
wait_review(fresh)
|
||||
assert fresh.review["sites"] == dialog.review["sites"]
|
||||
dialog.close()
|
||||
fresh.close()
|
||||
|
||||
|
||||
def test_baseline_image_matches_first_reviewed_zero_frame(session):
|
||||
@@ -301,15 +312,12 @@ def test_quality_ignores_unconfirmed_data_and_unmatched_loads(repeated_session):
|
||||
assert quality["hysteresis"] == []
|
||||
|
||||
|
||||
def test_quality_dialog_is_reachable_and_shows_validation_tables(qt_app, repeated_session, monkeypatch, tmp_path):
|
||||
def test_quality_dialog_is_reachable_and_shows_validation_tables(qt_app, repeated_session, monkeypatch, tmp_path, review_dialog):
|
||||
from PySide6.QtWidgets import QTableWidget
|
||||
from orisys_autocal.ui.session_review_dialog import SessionReviewDialog
|
||||
from orisys_autocal.ui.quality_review_dialog import QualityReviewDialog
|
||||
|
||||
directory, selections = repeated_session
|
||||
review = SessionReviewDialog(directory)
|
||||
review.review = review_session(directory, selections=selections)
|
||||
review._show_site()
|
||||
review = review_dialog(directory, review=review_session(directory, selections=selections))
|
||||
opened = []
|
||||
monkeypatch.setattr(QualityReviewDialog, "exec", lambda dialog: opened.append(dialog))
|
||||
review.quality_button.click()
|
||||
@@ -328,4 +336,3 @@ def test_quality_dialog_is_reachable_and_shows_validation_tables(qt_app, repeate
|
||||
qt_app.processEvents()
|
||||
assert dialog.grab().save(str(tmp_path / "validation.png"))
|
||||
dialog.close()
|
||||
review.close()
|
||||
|
||||
Reference in New Issue
Block a user