fix: 任务执行前检查 Android 设备连接 (#84)

This commit is contained in:
chengma
2026-08-10 09:35:46 +08:00
parent dee9f34035
commit e7fb06d7aa
11 changed files with 360 additions and 25 deletions
+101
View File
@@ -12,6 +12,7 @@ os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
from PyQt5.QtWidgets import QApplication
from src.android_device_service import AndroidDeviceSearchError
from src.pdd_ui import PDDTaskPage
from src.admin_gateway import AdminGatewayError, AdminTask, SubmissionReceipt
from src.pdd_ui_event import (
@@ -238,8 +239,14 @@ class PDDTaskPageEventTest(unittest.TestCase):
self.temp_directory = tempfile.TemporaryDirectory()
self.db_path = Path(self.temp_directory.name) / "client.db"
self.repository = TaskRepository(self.db_path)
self.device_checker_patch = patch(
"src.pdd_ui_event.AndroidDeviceService.require_connected",
autospec=True,
)
self.device_checker_patch.start()
def tearDown(self):
self.device_checker_patch.stop()
self.temp_directory.cleanup()
def _add_task(
@@ -481,6 +488,97 @@ class PDDTaskPageEventTest(unittest.TestCase):
events.shutdown()
page.deleteLater()
def test_disconnected_device_stops_auto_fetch_before_claim(self):
page = PDDTaskPage()
gateway = RecordingClaimGateway(collect_admin_task())
checker_threads = []
def disconnected(_serial):
checker_threads.append(threading.get_ident())
raise AndroidDeviceSearchError("USB Android 设备 USB-001 未连接")
events = PDDTaskPageEvent(
page,
self.repository,
claim_gateway=gateway,
settings_repository=self._saved_settings(),
collect_service_factory=fake_collect_factory,
device_connection_checker=disconnected,
)
page.autoFetchRequested.emit()
self.assertTrue(wait_until(self.app, lambda: not events._claim_busy))
self.assertEqual(gateway.calls, [])
self.assertEqual(self.repository.count_tasks(), 0)
self.assertEqual(len(checker_threads), 1)
self.assertNotEqual(checker_threads[0], threading.get_ident())
self.assertIn("Android 设备不可用", page.statusLabel.text())
self.assertIsNotNone(events._device_feedback)
events.shutdown()
page.deleteLater()
def test_disconnected_rerun_keeps_existing_task_unchanged(self):
self._add_task(1)
first = self.repository.start_collect_run("PDD-001", "USB-001")
event = self.repository.save_collect_result(
"PDD-001", first.attempt_id, FakeCollectResult().to_pdd_data()
)
self.repository.mark_outbox_sent(event.id)
before = self.repository.get_task("PDD-001")
before_run = self.repository.latest_task_run("PDD-001")
page = PDDTaskPage()
def disconnected(_serial):
raise AndroidDeviceSearchError(
"USB Android 设备 USB-001 未连接"
)
events = PDDTaskPageEvent(
page,
self.repository,
claim_gateway=RecordingClaimGateway(),
settings_repository=self._saved_settings(),
collect_service_factory=fake_collect_factory,
device_connection_checker=disconnected,
)
with patch("src.pdd_ui_event.MessageBox") as message_box:
message_box.return_value.exec.return_value = True
page.rerunRequested.emit("PDD-001")
self.assertTrue(wait_until(self.app, lambda: not events._claim_busy))
after = self.repository.get_task("PDD-001")
after_run = self.repository.latest_task_run("PDD-001")
self.assertEqual(after.status, TaskStatus.SUCCEEDED)
self.assertEqual(after.pdd_data, before.pdd_data)
self.assertEqual(after_run.attempt_id, before_run.attempt_id)
self.assertIn("重新采集未开始", page.statusLabel.text())
events.shutdown()
page.deleteLater()
def test_device_feedback_opens_settings_closes_and_does_not_stack(self):
page = PDDTaskPage()
events = PDDTaskPageEvent(page, self.repository)
opened = []
page.openSettingsRequested.connect(lambda: opened.append(True))
events._show_device_unavailable("第一条")
first = events._device_feedback
events._show_device_unavailable("第二条")
second = events._device_feedback
self.assertIsNot(first, second)
buttons = {
button.text(): button
for button in second.findChildren(type(page.rerunButton))
}
self.assertIn("打开设置", buttons)
self.assertIn("关闭提示", buttons)
buttons["打开设置"].click()
self.app.processEvents()
self.assertEqual(opened, [True])
self.assertIsNone(events._device_feedback)
events.shutdown()
page.deleteLater()
def test_query_failure_shows_readable_error(self):
page = PDDTaskPage()
events = PDDTaskPageEvent(page, BrokenRepository())
@@ -587,6 +685,9 @@ class PDDTaskPageEventTest(unittest.TestCase):
create_u2_purchase_adapter,
)
self.assertEqual(window.pddTaskPage.taskModel.data_row_count(), 0)
window.pddTaskPage.openSettingsRequested.emit()
self.app.processEvents()
self.assertIs(window.stackedWidget.currentWidget(), window.settingsPage)
window.close()
window.deleteLater()