594 lines
24 KiB
Python
594 lines
24 KiB
Python
import unittest
|
|
from pathlib import Path
|
|
from tempfile import TemporaryDirectory
|
|
from unittest.mock import Mock, patch
|
|
|
|
from upload_video_to_guanghe import (
|
|
GuangHeUploader,
|
|
TmallTitleGenerationError,
|
|
_match_tm_item_ids_from_product_titles,
|
|
_select_video_product_names,
|
|
_tm_product_title_search_pattern,
|
|
download_videos,
|
|
)
|
|
|
|
|
|
def test_tm_product_title_search_pattern_uses_model_token() -> None:
|
|
assert _tm_product_title_search_pattern("拾影单肩包") == "%拾影%"
|
|
assert _tm_product_title_search_pattern("星云mini") == "%星云mini%"
|
|
|
|
|
|
def test_multi_style_record_prefers_style_named_by_attachment() -> None:
|
|
assert _select_video_product_names(
|
|
["阿波罗2", "宙斯3"], "宙斯3 7.30.mp4"
|
|
) == ["宙斯3"]
|
|
assert _select_video_product_names(
|
|
["阿波罗2", "宙斯3"], "7月30日.mp4"
|
|
) == ["阿波罗2", "宙斯3"]
|
|
|
|
|
|
def test_attachment_style_matching_handles_combos_and_overlapping_aliases() -> None:
|
|
assert _select_video_product_names(
|
|
["阿波罗2", "宙斯3", "星云2", "逐星"],
|
|
"宙斯3+阿波罗2+星云2+逐星.m4v",
|
|
) == ["宙斯3", "阿波罗2", "星云2", "逐星"]
|
|
assert _select_video_product_names(
|
|
["极星双肩", "极星双肩2"], "极星双肩2 新新新.mp4"
|
|
) == ["极星双肩2"]
|
|
|
|
|
|
class GuangHeMetadataTests(unittest.TestCase):
|
|
def test_formal_title_rejection_uses_non_browser_failure_type(self):
|
|
GuangHeUploader.configure_catalog_product_titles(
|
|
{"极星双肩2": ["极星双肩2双肩包轻便电脑包"]}
|
|
)
|
|
uploader = GuangHeUploader("", "", require_llm_titles=True)
|
|
try:
|
|
with patch(
|
|
"upload_video_to_guanghe.JdVideoTitleGenerator.generate",
|
|
side_effect=RuntimeError("候选不合格"),
|
|
):
|
|
with self.assertRaisesRegex(
|
|
TmallTitleGenerationError, "候选不合格"
|
|
):
|
|
uploader._generate_title(["极星双肩2"], video_key="token")
|
|
finally:
|
|
GuangHeUploader.configure_catalog_product_titles({})
|
|
|
|
def test_formal_collection_title_forbids_specific_style_names(self):
|
|
GuangHeUploader.configure_catalog_product_titles(
|
|
{
|
|
"宙斯3": ["宙斯3双肩包男士大容量"],
|
|
"阿波罗2": ["阿波罗2电脑包手提轻便"],
|
|
}
|
|
)
|
|
uploader = GuangHeUploader("", "", require_llm_titles=True)
|
|
try:
|
|
with patch(
|
|
"upload_video_to_guanghe.JdVideoTitleGenerator"
|
|
) as generator_class:
|
|
generator = generator_class.return_value
|
|
generator.generate.return_value = (
|
|
"多款通勤包袋,大容量轻便按场景切换"
|
|
)
|
|
title = uploader._generate_title(
|
|
["宙斯3", "阿波罗2"], video_key="combo-token"
|
|
)
|
|
self.assertEqual(title, "多款通勤包袋,大容量轻便按场景切换")
|
|
self.assertTrue(generator_class.call_args.kwargs["generic_collection"])
|
|
self.assertFalse(generator_class.call_args.kwargs["require_product_name"])
|
|
self.assertEqual(generator_class.call_args.kwargs["llm_timeout"], 300)
|
|
generator.generate.assert_called_once()
|
|
self.assertEqual(
|
|
generator.generate.call_args.args[0], ["宙斯3", "阿波罗2"]
|
|
)
|
|
finally:
|
|
GuangHeUploader.configure_catalog_product_titles({})
|
|
|
|
def test_downloads_with_same_attachment_name_are_isolated_by_record(self):
|
|
attachment = {"file_token": "file-token", "name": "same-name.mp4"}
|
|
|
|
with TemporaryDirectory() as tmp_dir, patch(
|
|
"upload_video_to_guanghe.DOWNLOAD_DIR", Path(tmp_dir)
|
|
), patch("upload_video_to_guanghe.run_lark") as run_lark_mock:
|
|
def fake_download(args, *, cwd=None, timeout=None):
|
|
self.assertEqual(timeout, 600)
|
|
output_dir = Path(cwd)
|
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
(output_dir / args[args.index("--output") + 1]).write_bytes(b"video")
|
|
return 0, "", ""
|
|
|
|
run_lark_mock.side_effect = fake_download
|
|
|
|
first = download_videos("record-one", [attachment])
|
|
second = download_videos("record-two", [attachment])
|
|
|
|
self.assertEqual(first[0].parent.parent.name, "record-one")
|
|
self.assertEqual(second[0].parent.parent.name, "record-two")
|
|
self.assertEqual(first[0].parent.name, "file-token")
|
|
self.assertNotEqual(first[0], second[0])
|
|
|
|
def test_unresolved_style_uses_exact_database_product_title_match(self):
|
|
result = _match_tm_item_ids_from_product_titles(
|
|
["宙斯3", "未建档款"],
|
|
[
|
|
(
|
|
"986141740958",
|
|
"GYXX/光影行星宙斯3双肩包男士背包机能大容量",
|
|
),
|
|
("655191144133", "GYXX光影行星宙斯双肩包男士电脑包"),
|
|
],
|
|
)
|
|
|
|
self.assertEqual(result, {"宙斯3": ["986141740958"]})
|
|
|
|
def test_product_search_term_removes_series_suffix(self):
|
|
self.assertEqual(
|
|
GuangHeUploader._normalize_product_search_term("宙斯系列"),
|
|
"宙斯",
|
|
)
|
|
self.assertEqual(
|
|
GuangHeUploader._normalize_product_search_term(" 宙斯 系列款 "),
|
|
"宙斯",
|
|
)
|
|
self.assertEqual(
|
|
GuangHeUploader._normalize_product_search_term("星迹2"),
|
|
"星迹2",
|
|
)
|
|
|
|
def test_cover_generation_pending_marker_is_not_upload_done(self):
|
|
self.assertTrue(GuangHeUploader._cover_generation_is_pending("封面生成中"))
|
|
self.assertFalse(GuangHeUploader._cover_generation_is_pending("智能封面图"))
|
|
|
|
def test_content_label_option_allows_browse_count_but_rejects_longer_label(self):
|
|
self.assertTrue(
|
|
GuangHeUploader._content_label_text_matches("# 斜挎包 41673031次浏览", "斜挎包")
|
|
)
|
|
self.assertTrue(
|
|
GuangHeUploader._content_label_text_matches("商品展示", "商品展示")
|
|
)
|
|
self.assertTrue(
|
|
GuangHeUploader._content_label_text_matches("#斜挎包", "斜挎包")
|
|
)
|
|
self.assertFalse(
|
|
GuangHeUploader._content_label_text_matches("# 单肩斜挎包 32871826次浏览", "斜挎包")
|
|
)
|
|
|
|
def test_topic_result_card_requires_topic_and_activity_statistics(self):
|
|
self.assertTrue(
|
|
GuangHeUploader._topic_result_card_text_matches(
|
|
"# 我的夏日焕新清单 小二推荐 作品数469.5万 参与数16.2万",
|
|
"我的夏日焕新清单",
|
|
)
|
|
)
|
|
self.assertTrue(
|
|
GuangHeUploader._topic_result_card_text_matches(
|
|
"# 秋上新开拍了 时尚 作品数198.3万 参与数11.3万",
|
|
"秋上新",
|
|
)
|
|
)
|
|
self.assertFalse(
|
|
GuangHeUploader._topic_result_card_text_matches(
|
|
"我的夏日焕新清单",
|
|
"我的夏日焕新清单",
|
|
)
|
|
)
|
|
self.assertTrue(GuangHeUploader._topic_card_box_is_clickable(620, 120))
|
|
self.assertFalse(GuangHeUploader._topic_card_box_is_clickable(620, 45))
|
|
self.assertFalse(GuangHeUploader._topic_card_box_is_clickable(720, 600))
|
|
|
|
def test_poseidon_edge_uses_authoritative_tote_category(self):
|
|
self.assertEqual(
|
|
GuangHeUploader._resolve_title_category(
|
|
"波塞冬edge",
|
|
"双肩包、电脑包、托特包、大容量",
|
|
),
|
|
"托特包",
|
|
)
|
|
self.assertEqual(
|
|
GuangHeUploader._resolve_title_category("星迹2", ""),
|
|
"斜挎包",
|
|
)
|
|
|
|
def test_invalid_online_info_is_rejected_when_main_category_conflicts(self):
|
|
result = GuangHeUploader._validate_online_product_info(
|
|
"波塞冬edge",
|
|
"主包型:双肩包;尺寸:39cm;容量/适配:16寸;材质:尼龙;卖点:分区",
|
|
)
|
|
self.assertEqual(result, "")
|
|
|
|
def test_verified_fallback_info_contains_all_product_fields(self):
|
|
info = GuangHeUploader._verified_product_info("星迹2")
|
|
for field in ["主包型:", "尺寸:", "容量/适配:", "材质:", "卖点:"]:
|
|
self.assertIn(field, info)
|
|
self.assertIn("斜挎包", info)
|
|
|
|
def test_title_category_uses_name_then_search_features(self):
|
|
self.assertEqual(
|
|
GuangHeUploader._resolve_title_category("盖亚斜挎", "轻量、大容量"),
|
|
"斜挎包",
|
|
)
|
|
self.assertEqual(
|
|
GuangHeUploader._resolve_title_category("宙斯", "双肩包、大容量、笔电仓"),
|
|
"双肩包",
|
|
)
|
|
|
|
def test_title_normalization_keeps_search_structure_and_uses_computer_bag_term(self):
|
|
title = GuangHeUploader._normalize_generated_title(
|
|
"宙斯笔电大容量通勤真能装",
|
|
["宙斯"],
|
|
"双肩包",
|
|
)
|
|
|
|
self.assertTrue(title.startswith("宙斯双肩包,"))
|
|
self.assertTrue(title.endswith("!"))
|
|
self.assertIn("电脑包", title)
|
|
self.assertNotIn("笔电", title)
|
|
self.assertNotIn("笔记本电脑", title)
|
|
self.assertNotIn("电脑包仓", title)
|
|
self.assertGreaterEqual(len(title), 26)
|
|
self.assertLessEqual(len(title), 30)
|
|
|
|
def test_title_normalization_removes_compact_duplicate_model_and_broken_tail(self):
|
|
title = GuangHeUploader._normalize_generated_title(
|
|
"光影行星宙斯zair双肩包,宙斯zair,大容量分区收纳,从容应",
|
|
["宙斯z air"],
|
|
"双肩包",
|
|
)
|
|
|
|
self.assertTrue(title.startswith("宙斯z air双肩包,"))
|
|
self.assertEqual(title.replace(" ", "").count("宙斯zair"), 1)
|
|
self.assertNotIn("从容应!", title)
|
|
self.assertGreaterEqual(len(title), 26)
|
|
self.assertLessEqual(len(title), 30)
|
|
|
|
def test_same_style_multiple_videos_get_distinct_titles_when_model_repeats(self):
|
|
uploader = object.__new__(GuangHeUploader)
|
|
repeated = "光影行星宙斯双肩包科学分区收纳轻量通勤出行"
|
|
with (
|
|
patch.object(uploader, "_search_product_features", return_value=""),
|
|
patch("upload_video_to_guanghe.call_direct_llm", return_value=(repeated, {})),
|
|
):
|
|
first = uploader._generate_title(["宙斯"], video_index=1, video_total=2)
|
|
second = uploader._generate_title(["宙斯"], video_index=2, video_total=2)
|
|
|
|
self.assertNotEqual(first, second)
|
|
self.assertTrue(first.startswith("宙斯双肩包,"))
|
|
self.assertTrue(second.startswith("宙斯双肩包,"))
|
|
|
|
def test_same_style_repeated_model_copy_gets_low_similarity_bodies(self):
|
|
uploader = object.__new__(GuangHeUploader)
|
|
repeated = "光影行星宙斯双肩包,科学分区收纳,轻量通勤出行!"
|
|
with (
|
|
patch.object(uploader, "_search_product_features", return_value=""),
|
|
patch("upload_video_to_guanghe.call_direct_llm", return_value=(repeated, {})),
|
|
):
|
|
titles = [
|
|
uploader._generate_title(["宙斯"], video_index=index, video_total=4)
|
|
for index in range(1, 5)
|
|
]
|
|
|
|
bodies = [GuangHeUploader._title_body(title) for title in titles]
|
|
self.assertEqual(len(set(bodies)), 4)
|
|
for index, body in enumerate(bodies):
|
|
for other in bodies[index + 1:]:
|
|
self.assertLess(
|
|
GuangHeUploader._title_similarity(body, other),
|
|
GuangHeUploader.TITLE_SIMILARITY_LIMIT,
|
|
)
|
|
|
|
def test_different_styles_cannot_reuse_same_title_skeleton(self):
|
|
uploader = object.__new__(GuangHeUploader)
|
|
repeated = "科学分区收纳,轻装通勤出行"
|
|
with (
|
|
patch.object(uploader, "_search_product_features", return_value=""),
|
|
patch("upload_video_to_guanghe.call_direct_llm", return_value=(repeated, {})),
|
|
):
|
|
first = uploader._generate_title(["宙斯"], video_index=1)
|
|
second = uploader._generate_title(["星云2"], video_index=1)
|
|
|
|
first_body = GuangHeUploader._title_body(first)
|
|
second_body = GuangHeUploader._title_body(second)
|
|
self.assertLess(
|
|
GuangHeUploader._title_similarity(first_body, second_body),
|
|
GuangHeUploader.TITLE_SIMILARITY_LIMIT,
|
|
)
|
|
|
|
def test_title_similarity_ignores_product_prefix(self):
|
|
first = "宙斯双肩包,科学分区收纳,轻装通勤出行!"
|
|
second = "星云2斜挎包,科学分区收纳,轻装通勤出行!"
|
|
|
|
self.assertEqual(GuangHeUploader._title_similarity(first, second), 1.0)
|
|
|
|
def test_full_batch_can_claim_48_globally_distinct_title_bodies(self):
|
|
uploader = object.__new__(GuangHeUploader)
|
|
titles = []
|
|
for index in range(48):
|
|
product_names = [f"款式{index % 12 + 1}"]
|
|
video_index = index // 12 + 1
|
|
candidate = uploader._fallback_title(
|
|
product_names,
|
|
"双肩包",
|
|
variant_index=video_index,
|
|
)
|
|
titles.append(
|
|
uploader._claim_unique_title(
|
|
candidate,
|
|
product_names,
|
|
"双肩包",
|
|
variant_index=video_index,
|
|
)
|
|
)
|
|
|
|
self.assertEqual(len(set(titles)), 48)
|
|
self.assertTrue(all(26 <= len(title) <= 30 for title in titles))
|
|
for index, title in enumerate(titles):
|
|
for other in titles[index + 1:]:
|
|
self.assertLess(
|
|
GuangHeUploader._title_similarity(title, other),
|
|
GuangHeUploader.TITLE_SIMILARITY_LIMIT,
|
|
)
|
|
|
|
def test_two_store_uploaders_can_share_one_global_title_registry(self):
|
|
shared_global = []
|
|
shared_styles = {}
|
|
shared_usage = {}
|
|
first_uploader = object.__new__(GuangHeUploader)
|
|
second_uploader = object.__new__(GuangHeUploader)
|
|
for uploader in (first_uploader, second_uploader):
|
|
uploader._used_titles_global = shared_global
|
|
uploader._used_titles_by_products = shared_styles
|
|
uploader._title_variant_usage = shared_usage
|
|
|
|
first = first_uploader._claim_unique_title(
|
|
first_uploader._fallback_title(["宙斯"], "双肩包", 1),
|
|
["宙斯"],
|
|
"双肩包",
|
|
1,
|
|
)
|
|
second = second_uploader._claim_unique_title(
|
|
second_uploader._fallback_title(["星云2"], "斜挎包", 1),
|
|
["星云2"],
|
|
"斜挎包",
|
|
1,
|
|
)
|
|
|
|
self.assertLess(
|
|
GuangHeUploader._title_similarity(first, second),
|
|
GuangHeUploader.TITLE_SIMILARITY_LIMIT,
|
|
)
|
|
|
|
def test_product_search_specs_prefer_tm_item_ids_and_fallback_to_keyword(self):
|
|
specs = GuangHeUploader._build_product_search_specs(
|
|
["星云2", "未建档系列款"],
|
|
{"星云2": ["900176117674", "865283623976"]},
|
|
)
|
|
|
|
self.assertEqual(
|
|
specs,
|
|
[
|
|
{
|
|
"product_name": "星云2",
|
|
"search_term": "900176117674",
|
|
"exact_id": True,
|
|
},
|
|
{
|
|
"product_name": "未建档系列款",
|
|
"search_term": "未建档",
|
|
"exact_id": False,
|
|
},
|
|
{
|
|
"product_name": "星云2",
|
|
"search_term": "865283623976",
|
|
"exact_id": True,
|
|
},
|
|
],
|
|
)
|
|
|
|
def test_exact_id_searches_get_one_store_keyword_fallback(self):
|
|
specs = GuangHeUploader._build_product_search_specs(
|
|
["极星双肩", "未建档款"],
|
|
{"极星双肩": ["972285625931", "966753757238"]},
|
|
)
|
|
|
|
self.assertEqual(
|
|
GuangHeUploader._build_exact_search_fallback_specs(specs),
|
|
[
|
|
{
|
|
"product_name": "极星双肩",
|
|
"search_term": "极星双肩",
|
|
"exact_id": False,
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_title_fallback_contains_product_category_solution_and_result(self):
|
|
title = GuangHeUploader._fallback_title(["盖亚斜挎"], "斜挎包")
|
|
|
|
self.assertTrue(title.startswith("盖亚斜挎包,"))
|
|
self.assertIn(",", title)
|
|
self.assertTrue(title.endswith("!"))
|
|
self.assertIn("钥匙卡包各归其位", title)
|
|
self.assertIn("早高峰取物", title)
|
|
self.assertGreaterEqual(title.count(","), 2)
|
|
self.assertGreaterEqual(len(title), 26)
|
|
self.assertLessEqual(len(title), 30)
|
|
|
|
def test_generated_title_replaces_generic_category_with_model_category(self):
|
|
uploader = object.__new__(GuangHeUploader)
|
|
with (
|
|
patch.object(uploader, "_search_product_features", return_value=""),
|
|
patch(
|
|
"upload_video_to_guanghe.call_direct_llm",
|
|
return_value=("光影行星宙斯双肩包大容量笔记本电脑轻量通勤", {}),
|
|
),
|
|
):
|
|
title = uploader._generate_title(["宙斯"])
|
|
|
|
self.assertTrue(title.startswith("宙斯双肩包,"))
|
|
self.assertNotIn("包袋双肩包", title)
|
|
|
|
def test_generated_poseidon_title_cannot_be_changed_to_backpack_by_model(self):
|
|
uploader = object.__new__(GuangHeUploader)
|
|
with (
|
|
patch.object(
|
|
uploader,
|
|
"_search_product_features",
|
|
return_value="双肩包、电脑包、托特包、大容量",
|
|
),
|
|
patch(
|
|
"upload_video_to_guanghe.call_direct_llm",
|
|
return_value=(
|
|
"光影行星波塞冬edge双肩包暴雨通勤防泼水电脑仓从容出行",
|
|
{},
|
|
),
|
|
),
|
|
):
|
|
title = uploader._generate_title(["波塞冬edge"])
|
|
|
|
self.assertTrue(title.startswith("波塞冬edge托特包,"))
|
|
self.assertNotIn("双肩包", title)
|
|
self.assertTrue(title.endswith("!"))
|
|
self.assertGreaterEqual(len(title), 26)
|
|
self.assertLessEqual(len(title), 30)
|
|
|
|
def test_primary_content_label_uses_first_product_bag_type(self):
|
|
self.assertEqual(
|
|
GuangHeUploader._content_label_for_products(["盖亚斜挎", "极星双肩"]),
|
|
"斜挎包",
|
|
)
|
|
self.assertEqual(
|
|
GuangHeUploader._content_label_for_products(["盖亚微单"]),
|
|
"相机包",
|
|
)
|
|
self.assertEqual(
|
|
GuangHeUploader._content_label_for_products(["波塞冬edge"]),
|
|
"托特包",
|
|
)
|
|
self.assertEqual(
|
|
GuangHeUploader._content_label_for_products(["波塞冬手提电脑包"]),
|
|
"电脑包",
|
|
)
|
|
|
|
def test_catalog_product_titles_supply_style_category_and_verified_info(self):
|
|
try:
|
|
GuangHeUploader.configure_catalog_product_titles(
|
|
{
|
|
"星云2": [
|
|
"GYXX光影行星星云2斜挎包男士单肩包平板胸包",
|
|
"光影行星星云斜挎包男款邮差单肩包",
|
|
],
|
|
"宙斯": ["GYXX光影行星宙斯双肩包男大容量通勤背包"],
|
|
"宙斯z air": ["光影行星宙斯zair双肩包电脑包通勤背包"],
|
|
"黑曜石托特": ["光影行星黑曜石双肩托特多用包"],
|
|
}
|
|
)
|
|
|
|
self.assertEqual(
|
|
GuangHeUploader._content_label_for_products(["星云2"]),
|
|
"斜挎包",
|
|
)
|
|
self.assertEqual(
|
|
GuangHeUploader._resolve_title_category("宙斯"),
|
|
"双肩包",
|
|
)
|
|
self.assertIn(
|
|
"主包型:斜挎包",
|
|
GuangHeUploader._verified_product_info("星云2"),
|
|
)
|
|
self.assertEqual(
|
|
GuangHeUploader._content_label_for_products(["宙斯z air"]),
|
|
"双肩包",
|
|
)
|
|
self.assertEqual(
|
|
GuangHeUploader._content_label_for_products(["黑曜石托特"]),
|
|
"托特包",
|
|
)
|
|
finally:
|
|
GuangHeUploader.configure_catalog_product_titles({})
|
|
|
|
def test_metadata_selects_style_category_and_product_showcase_before_topic(self):
|
|
cases = [
|
|
(["盖亚斜挎"], ["斜挎包", "商品展示"]),
|
|
(["极星双肩"], ["双肩包", "商品展示"]),
|
|
]
|
|
for product_names, expected_labels in cases:
|
|
with self.subTest(product_names=product_names):
|
|
uploader = object.__new__(GuangHeUploader)
|
|
calls = []
|
|
uploader._pick_content_label = Mock(
|
|
side_effect=lambda label: calls.append(("label", label))
|
|
)
|
|
uploader._pick_topic = Mock(
|
|
side_effect=lambda topic: calls.append(("topic", topic))
|
|
)
|
|
uploader._snapshot = Mock()
|
|
|
|
uploader._prepare_publish_metadata(product_names)
|
|
|
|
self.assertEqual(
|
|
calls,
|
|
[
|
|
*[("label", label) for label in expected_labels],
|
|
("topic", "我的夏日焕新清单"),
|
|
],
|
|
)
|
|
|
|
def test_fixed_content_labels_only_keep_product_showcase(self):
|
|
self.assertEqual(GuangHeUploader.FIXED_CONTENT_LABELS, ("商品展示",))
|
|
self.assertNotIn("户外", GuangHeUploader.FIXED_CONTENT_LABELS)
|
|
|
|
def test_missing_user_selected_topic_stops_metadata_preparation(self):
|
|
uploader = object.__new__(GuangHeUploader)
|
|
uploader._pick_content_label = Mock()
|
|
uploader._pick_topic = Mock(
|
|
side_effect=RuntimeError("没有找到固定话题: #我的夏日焕新清单")
|
|
)
|
|
uploader._snapshot = Mock()
|
|
|
|
with self.assertRaisesRegex(RuntimeError, "没有找到固定话题"):
|
|
uploader._prepare_publish_metadata(["极星双肩"])
|
|
|
|
self.assertEqual(
|
|
uploader._pick_content_label.call_args_list,
|
|
[unittest.mock.call("双肩包"), unittest.mock.call("商品展示")],
|
|
)
|
|
|
|
def test_optional_content_label_failures_do_not_skip_required_topic(self):
|
|
uploader = object.__new__(GuangHeUploader)
|
|
uploader.page = Mock()
|
|
uploader._pick_content_label = Mock(
|
|
side_effect=[
|
|
RuntimeError("内容标签没有精确匹配项: #双肩包"),
|
|
RuntimeError("内容标签没有精确匹配项: #商品展示"),
|
|
]
|
|
)
|
|
uploader._pick_topic = Mock()
|
|
uploader._snapshot = Mock()
|
|
|
|
uploader._prepare_publish_metadata(["极星双肩"])
|
|
|
|
self.assertEqual(
|
|
uploader._pick_content_label.call_args_list,
|
|
[unittest.mock.call("双肩包"), unittest.mock.call("商品展示")],
|
|
)
|
|
uploader._pick_topic.assert_called_once_with("我的夏日焕新清单")
|
|
|
|
def test_metadata_uses_operator_topic_keyword(self):
|
|
uploader = object.__new__(GuangHeUploader)
|
|
calls = []
|
|
uploader._pick_content_label = Mock()
|
|
uploader._pick_topic = Mock(side_effect=lambda topic: calls.append(topic))
|
|
uploader._snapshot = Mock()
|
|
|
|
uploader._prepare_publish_metadata(["极星双肩"], topic_keyword="秋上新")
|
|
|
|
self.assertEqual(calls, ["秋上新"])
|
|
|
|
def test_fixed_topic_is_not_a_recommended_first_result(self):
|
|
self.assertEqual(GuangHeUploader.FIXED_TOPIC, "我的夏日焕新清单")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|