224 行
9.6 KiB
PHP
224 行
9.6 KiB
PHP
<?php
|
|
/**
|
|
* 线上 3C 商品与分类完整性校验测试脚本
|
|
*
|
|
* 覆盖:
|
|
* 1. 分类层级与权重测试
|
|
* 2. 8 款 3C 商品与 SKU 价格/库存数据完整性测试
|
|
* 3. 前端接口模拟测试 (正常场景、业务失败场景、参数错误场景)
|
|
* 4. 装修模板 5 首页推荐联动验证
|
|
*/
|
|
|
|
namespace tests\goods;
|
|
|
|
define('APP_PATH', __DIR__ . '/../application/');
|
|
define('ROOT_PATH', dirname(realpath(APP_PATH)) . '/');
|
|
require_once __DIR__ . '/../thinkphp/base.php';
|
|
require_once __DIR__ . '/../thinkphp/helper.php';
|
|
require_once __DIR__ . '/../application/common.php';
|
|
|
|
if (is_file(ROOT_PATH . '.env')) {
|
|
$env = parse_ini_file(ROOT_PATH . '.env', true);
|
|
foreach ($env as $key => $val) {
|
|
$name = 'PHP_' . strtoupper($key);
|
|
if (is_array($val)) {
|
|
foreach ($val as $k => $v) {
|
|
putenv("{$name}_" . strtoupper($k) . "={$v}");
|
|
}
|
|
} else {
|
|
putenv("{$name}={$val}");
|
|
}
|
|
}
|
|
}
|
|
|
|
\think\Config::set(\think\Config::load(APP_PATH . 'config.php'));
|
|
$dbConfig = [
|
|
'type' => 'mysql',
|
|
'hostname' => '127.0.0.1',
|
|
'database' => 'henglianshutong',
|
|
'username' => 'henglianshutong',
|
|
'password' => 'henglianshutong',
|
|
'hostport' => '3306',
|
|
'prefix' => 'hla_',
|
|
];
|
|
\think\Config::set('database', $dbConfig);
|
|
|
|
use think\Db;
|
|
|
|
class Verify3COnlineData
|
|
{
|
|
private $passed = 0;
|
|
private $failed = 0;
|
|
|
|
private function assert($condition, $message)
|
|
{
|
|
if ($condition) {
|
|
echo " [PASS] {$message}\n";
|
|
$this->passed++;
|
|
} else {
|
|
echo " [FAIL] {$message}\n";
|
|
$this->failed++;
|
|
}
|
|
}
|
|
|
|
public function run()
|
|
{
|
|
echo "====================================================\n";
|
|
echo "开始验证 3C 商品与分类线上数据及 API 接口...\n";
|
|
echo "====================================================\n\n";
|
|
|
|
// 1. 分类检验
|
|
echo "--- 场景 1: 分类层级与权重检验 ---\n";
|
|
$topCategory = Db::name('shopro_category')
|
|
->where('parent_id', 0)
|
|
->where('status', 'normal')
|
|
->order('weigh', 'desc')
|
|
->order('id', 'desc')
|
|
->find();
|
|
$this->assert(!empty($topCategory), "获取当前生效一级主分类成功 (ID: {$topCategory['id']}, 名称: {$topCategory['name']})");
|
|
|
|
$categories = Db::name('shopro_category')
|
|
->where('parent_id', $topCategory['id'])
|
|
->where('status', 'normal')
|
|
->order('weigh', 'desc')
|
|
->select();
|
|
|
|
$catNames = array_column($categories, 'name');
|
|
$this->assert(in_array('手机数码', $catNames), "分类列表中包含 '手机数码'");
|
|
$this->assert(in_array('智能影音', $catNames), "分类列表中包含 '智能影音'");
|
|
$this->assert(in_array('智能穿戴', $catNames), "分类列表中包含 '智能穿戴'");
|
|
$this->assert(in_array('电脑办公', $catNames), "分类列表中包含 '电脑办公'");
|
|
|
|
// 校验权重排在前面
|
|
$top4Names = array_slice($catNames, 0, 4);
|
|
$this->assert(
|
|
in_array('手机数码', $top4Names) && in_array('智能影音', $top4Names),
|
|
"前 4 大展示分类全部为 3C 核心品类"
|
|
);
|
|
|
|
// 2. 商品检验
|
|
echo "\n--- 场景 2: 8 款主流 3C 商品及 SKU 检验 ---\n";
|
|
$titles = [
|
|
'倍思 65W GaN氮化镓多口快充充电器',
|
|
'漫步者 LolliPods 真无线立体声蓝牙耳机',
|
|
'罗马仕 20000mAh 22.5W超级快充移动电源',
|
|
'华为手环 8 智能运动健康手环 曜石黑',
|
|
'小米Redmi Watch 3 青春版 智能蓝牙通话手表',
|
|
'罗技 M330 降噪静音无线鼠标 曜石黑',
|
|
'绿联 六合一Type-C多功能扩展坞',
|
|
'品胜 苹果PD 20W快充编织数据线 1.2米'
|
|
];
|
|
|
|
$goodsList = Db::name('shopro_goods')
|
|
->whereIn('title', $titles)
|
|
->whereNull('deletetime')
|
|
->select();
|
|
|
|
$this->assert(count($goodsList) === 8, "8 款 3C 商品均已完整入库并正常启用 (实际: " . count($goodsList) . ")");
|
|
|
|
$goodsIds = [];
|
|
foreach ($goodsList as $goods) {
|
|
$goodsIds[] = $goods['id'];
|
|
$this->assert($goods['status'] === 'up', "商品 [{$goods['title']}] 状态为正常上架 (up)");
|
|
$this->assert(!empty($goods['image']), "商品 [{$goods['title']}] 配备高清封面图");
|
|
|
|
$images = json_decode($goods['images'], true);
|
|
$this->assert(is_array($images) && count($images) >= 3, "商品 [{$goods['title']}] 包含 3 张高清轮播图");
|
|
|
|
$params = json_decode($goods['params'], true);
|
|
$this->assert(is_array($params) && count($params) >= 5, "商品 [{$goods['title']}] 包含完整规格参数指标 (≥5项)");
|
|
|
|
$this->assert(strpos($goods['content'], '正品保障') !== false, "商品 [{$goods['title']}] 详情包含正品与官方售后承诺");
|
|
|
|
// SKU 价格与库存
|
|
$sku = Db::name('shopro_goods_sku_price')->where('goods_id', $goods['id'])->find();
|
|
$this->assert(!empty($sku), "商品 [{$goods['title']}] 存在有效 SKU 价格记录");
|
|
$this->assert($sku['stock'] >= 1000, "商品 [{$goods['title']}] 库存充足 (当前库存: {$sku['stock']})");
|
|
$this->assert($sku['price'] > 0 && $sku['price'] == $goods['price'], "商品 [{$goods['title']}] 售价核验一致 ({$sku['price']}元)");
|
|
}
|
|
|
|
// 3. API 模拟测试
|
|
echo "\n--- 场景 3: API 模拟测试 (覆盖正常/业务失败/参数异常) ---\n";
|
|
|
|
// 3.1 正常场景: 查询分类下的商品
|
|
$mobileCat = Db::name('shopro_category')->where('parent_id', $topCategory['id'])->where('name', '手机数码')->find();
|
|
$mobileGoods = Db::name('shopro_goods')
|
|
->whereRaw("find_in_set({$mobileCat['id']}, category_ids)")
|
|
->where('status', 'up')
|
|
->whereNull('deletetime')
|
|
->select();
|
|
$this->assert(count($mobileGoods) >= 3, "API 模拟: 查询 [手机数码] 分类成功返回对应商品 (返回: " . count($mobileGoods) . "款)");
|
|
|
|
// 3.2 正常场景: 商品详情查询
|
|
$firstGoodsId = $goodsIds[0];
|
|
$detail = Db::name('shopro_goods')->where('id', $firstGoodsId)->where('status', 'up')->find();
|
|
$this->assert(!empty($detail) && $detail['id'] == $firstGoodsId, "API 模拟: 获取商品 ID [{$firstGoodsId}] 详情成功");
|
|
|
|
// 3.3 业务失败场景: 查询下架或不存在的商品
|
|
$nonExistDetail = Db::name('shopro_goods')->where('id', 999999)->where('status', 'up')->find();
|
|
$this->assert(empty($nonExistDetail), "API 模拟: 查询不存在商品 ID [999999] 正确返回空 (业务预期失败)");
|
|
|
|
// 3.4 参数异常场景: 空参数或非法分类 ID
|
|
$invalidCatGoods = Db::name('shopro_goods')
|
|
->whereRaw("find_in_set(-1, category_ids)")
|
|
->select();
|
|
$this->assert(empty($invalidCatGoods), "API 模拟: 传入非法分类 ID [-1] 正确返回空列表");
|
|
|
|
// 4. 装修模板 5 首页与 Tabbar 配置联动检验
|
|
echo "\n--- 场景 4: 装修模板 5 首页与 Tabbar 配置联动检验 ---\n";
|
|
$decorPage = Db::name('shopro_decorate_page')
|
|
->where('decorate_id', 5)
|
|
->where('type', 'home')
|
|
->find();
|
|
$this->assert(!empty($decorPage), "装修模板 5 (3C数码) home 页面记录存在");
|
|
|
|
if ($decorPage) {
|
|
$pageConfig = json_decode($decorPage['page'], true);
|
|
$found3CSearch = false;
|
|
$found3CGoods = false;
|
|
|
|
foreach ($pageConfig['data'] as $block) {
|
|
if ($block['type'] === 'searchBlock') {
|
|
if (strpos($block['data']['placeholder'], '65W') !== false || in_array('65W快充', $block['data']['keywords'])) {
|
|
$found3CSearch = true;
|
|
}
|
|
}
|
|
if ($block['type'] === 'goodsCard') {
|
|
if (isset($block['data']['goodsIds']) && !empty(array_intersect($block['data']['goodsIds'], $goodsIds))) {
|
|
$found3CGoods = true;
|
|
}
|
|
}
|
|
}
|
|
$this->assert($found3CSearch, "首页搜索框关键词已更新为 3C 数码热词");
|
|
$this->assert($found3CGoods, "首页推荐商品卡片已关联新生成的 3C 数码爆品");
|
|
}
|
|
|
|
// 校验 Tabbar 链接已指向当前主分类,杜绝死链
|
|
$basicPage = Db::name('shopro_decorate_page')->where('decorate_id', 5)->where('type', 'basic')->find();
|
|
if ($basicPage) {
|
|
$basicConfig = json_decode($basicPage['page'], true);
|
|
$tabbarCategoryUrl = '';
|
|
foreach ($basicConfig['tabbar']['list'] as $tab) {
|
|
if ($tab['text'] === '分类') {
|
|
$tabbarCategoryUrl = $tab['url'];
|
|
}
|
|
}
|
|
$this->assert(
|
|
$tabbarCategoryUrl === "/pages/index/category?id={$topCategory['id']}",
|
|
"Tabbar 分类链接正确指向当前有效顶级分类 ({$tabbarCategoryUrl})"
|
|
);
|
|
}
|
|
|
|
echo "\n====================================================\n";
|
|
echo "测试执行完成: 通过 {$this->passed} 项, 失败 {$this->failed} 项\n";
|
|
echo "====================================================\n";
|
|
|
|
if ($this->failed > 0) {
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
$verifier = new Verify3COnlineData();
|
|
$verifier->run();
|