109 lines
3.8 KiB
Python
109 lines
3.8 KiB
Python
"""PDD 页面分类与商品深链状态机测试。"""
|
|
|
|
from pathlib import Path
|
|
import unittest
|
|
import xml.etree.ElementTree as ET
|
|
|
|
from src.pdd_page_classifier import (
|
|
ACTION_NETWORK_ERROR,
|
|
ACTION_READY,
|
|
ACTION_REOPEN,
|
|
ACTION_UNAVAILABLE,
|
|
ACTION_WAIT,
|
|
PAGE_CAPTCHA,
|
|
PAGE_EXTERNAL,
|
|
PAGE_GOODS,
|
|
PAGE_HOME,
|
|
PAGE_LOADING,
|
|
PAGE_LOGIN_REQUIRED,
|
|
PAGE_NETWORK_ERROR,
|
|
PAGE_RISK_CONTROL,
|
|
GoodsOpenTracker,
|
|
classify_pdd_page,
|
|
)
|
|
|
|
|
|
FIXTURES = Path(__file__).parent / "fixtures"
|
|
PDD = "com.xunmeng.pinduoduo"
|
|
|
|
|
|
def observation(text: str, package: str = PDD):
|
|
xml = (
|
|
'<hierarchy><node package="{0}" class="android.widget.TextView" '
|
|
'text="{1}" bounds="[0,0][900,300]" visible-to-user="true"/>'
|
|
'<node package="{0}" text="占位一"/><node package="{0}" '
|
|
'text="占位二"/></hierarchy>'
|
|
).format(package, text)
|
|
return classify_pdd_page(ET.fromstring(xml), package)
|
|
|
|
|
|
class PddPageClassifierTest(unittest.TestCase):
|
|
def test_real_home_fixture_ignores_incorrect_focused_package(self) -> None:
|
|
root = ET.parse(FIXTURES / "pdd_home_page.xml").getroot()
|
|
|
|
result = classify_pdd_page(root, "com.android.settings")
|
|
|
|
self.assertEqual(PAGE_HOME, result.kind)
|
|
self.assertTrue(result.pdd_hierarchy)
|
|
|
|
def test_special_pages_are_not_home(self) -> None:
|
|
cases = {
|
|
"加载中": PAGE_LOADING,
|
|
"网络不给力": PAGE_NETWORK_ERROR,
|
|
"手机号登录": PAGE_LOGIN_REQUIRED,
|
|
"请完成验证": PAGE_CAPTCHA,
|
|
"操作频繁": PAGE_RISK_CONTROL,
|
|
"立即购买": PAGE_GOODS,
|
|
}
|
|
for label, expected in cases.items():
|
|
with self.subTest(label=label):
|
|
self.assertEqual(expected, observation(label).kind)
|
|
|
|
def test_browser_word_does_not_count_as_goods(self) -> None:
|
|
result = observation("立即购买", "com.android.chrome")
|
|
self.assertEqual(PAGE_EXTERNAL, result.kind)
|
|
|
|
def test_transient_home_can_reach_goods_without_reopen(self) -> None:
|
|
home = classify_pdd_page(
|
|
ET.parse(FIXTURES / "pdd_home_page.xml").getroot(), PDD
|
|
)
|
|
tracker = GoodsOpenTracker(None, 0.0)
|
|
|
|
self.assertEqual(ACTION_WAIT, tracker.observe(home, 2.0).action)
|
|
self.assertEqual(ACTION_WAIT, tracker.observe(home, 2.1).action)
|
|
self.assertEqual(
|
|
ACTION_READY, tracker.observe(observation("立即购买"), 2.2).action
|
|
)
|
|
|
|
def test_stable_home_reopens_once_then_marks_unavailable(self) -> None:
|
|
home = classify_pdd_page(
|
|
ET.parse(FIXTURES / "pdd_home_page.xml").getroot(), PDD
|
|
)
|
|
tracker = GoodsOpenTracker(None, 0.0)
|
|
|
|
for at in (2.0, 2.1):
|
|
self.assertEqual(ACTION_WAIT, tracker.observe(home, at).action)
|
|
self.assertEqual(ACTION_REOPEN, tracker.observe(home, 2.2).action)
|
|
tracker.reopened(3.0)
|
|
for at in (5.0, 5.1):
|
|
self.assertEqual(ACTION_WAIT, tracker.observe(home, at).action)
|
|
self.assertEqual(ACTION_UNAVAILABLE, tracker.observe(home, 5.2).action)
|
|
|
|
def test_old_goods_tree_is_not_accepted_as_new_target(self) -> None:
|
|
old = observation("旧商品标题 立即购买")
|
|
tracker = GoodsOpenTracker(old, 0.0)
|
|
|
|
self.assertEqual(ACTION_WAIT, tracker.observe(old, 0.2).action)
|
|
self.assertTrue(tracker.stale_goods_seen)
|
|
new = observation("目标商品标题 立即购买")
|
|
self.assertEqual(ACTION_READY, tracker.observe(new, 0.3).action)
|
|
|
|
def test_network_error_has_own_decision(self) -> None:
|
|
tracker = GoodsOpenTracker(None, 0.0)
|
|
decision = tracker.observe(observation("网络不给力"), 3.0)
|
|
self.assertEqual(ACTION_NETWORK_ERROR, decision.action)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|