如何用 SQL 查重复数据、空值、异常金额?
👔 Raina面试官: 重复数据、空值、异常金额,SQL 你怎么查?
🙋 候选人:
- 三类问题各有固定套路:GROUP BY 找重复、IS NULL 找空值、范围/精度规则找异常金额。
- 重复:GROUP BY 业务唯一键 HAVING COUNT(*) > 1,比如手机号、订单号。空值:WHERE col IS NULL OR col = '',注意空串和 NULL 都要覆盖。异常金额:amount < 0、amount = 0 但状态已支付、小数位超限、或同一订单行金额之和不等于总价。
- 测试发版前后可跑这些 SQL 做数据巡检,配合接口断言。发现异常要区分是脏数据还是业务规则允许,避免误报。
👔 Raina面试官: 金额异常除了负数还要查什么?
🙋 候选人:
- 还要查精度截断和汇总不一致。
- 比如订单头 total 与明细 sum(amount) 差一分钱;退款金额大于原支付;币种字段为空但金额有值。这些用 JOIN + 聚合对比最直接,也是财务类 bug 高发区。
索引是什么?什么情况下索引反而影响性能?
👔 Raina面试官: 索引是啥?啥情况下加了反而更慢?
🙋 候选人:
- 索引是加速查询的数据结构(常见 B+ 树),相当于给列建目录,WHERE/JOIN/ORDER BY 命中索引可少扫全表。
- 反而拖慢的场景:小表全表扫描更快;低选择性列(如性别)索引几乎无用;写多读少时每次 INSERT/UPDATE/DELETE 都要维护索引;过多索引占空间、拖慢 DDL;WHERE 对索引列做函数/隐式转换导致索引失效仍扫全表。
- 测试侧主要验:加索引后查询结果不变、关键列表接口 RT 改善;migration 加索引时大表锁表窗口是否可接受。性能回归比背八股更重要。
👔 Raina面试官: 你怎么判断查询有没有走索引?
🙋 候选人:
- 用 EXPLAIN 看 type、key、rows,type 至少到 range/ref,避免 ALL 全表扫。
- staging 大库上对比加索引前后执行计划和耗时;若优化器选错索引,结果可能对但很慢——这类要在性能测试里单独盯。
事务隔离级别有哪些?脏读、不可重复读、幻读怎么理解?
👔 Raina面试官: 事务隔离级别有哪些?脏读、不可重复读、幻读怎么理解?
🙋 候选人:
- SQL 标准四级:READ UNCOMMITTED → READ COMMITTED → REPEATABLE READ → SERIALIZABLE,隔离逐级增强,并发性能逐级下降。
- 脏读:A 读到 B 未提交的数据,B 回滚后 A 读到的是脏数据。不可重复读:A 同一事务内两次读同一行,B 中间提交修改,A 两次结果不同。幻读:A 两次范围查询,B 中间插入新行,A 第二次多出行——侧重行数变化。
- MySQL InnoDB 默认 RR 用 MVCC 缓解很多幻读;PostgreSQL 默认 RC。测试库存、余额、抢券要按实际隔离级别设计并发 case,不能假设一定无幻读。
👔 Raina面试官: 测试里怎么验这些现象?
🙋 候选人:
- 开两个 session 交错执行并控制 commit 时机,不是单线程能测出来的。
- 例如:session1 查库存=1 不提交;session2 扣库存提交;session1 再查或再扣,看是否超卖。自动化可用脚本模拟,但要标注环境隔离级别,否则预期会对不上。
软删除和硬删除有什么区别?测试时怎么验证?
👔 Raina面试官: 软删除和硬删除啥区别?测试怎么验?
🙋 候选人:
- 硬删除是物理 DELETE 行;软删除是打标记(如 deleted_at/is_deleted)行仍在库中,业务查询默认过滤。
- 验证软删:删后列表/详情不可见;直连 DB 行还在且标记正确;唯一键若含 deleted 状态,删后能否用同业务键再建。验证硬删:DB 行消失;关联外键/级联是否符合设计;审计日志是否仍保留操作记录。
- 还要测误删恢复:软删能否还原、硬删是否只能从备份恢复。接口返回 404 但库里还有数据——多半是软删,测试别只断言 HTTP 码。
👔 Raina面试官: 软删除对唯一约束有什么坑?
🙋 候选人:
- 经典坑是软删后无法复用同一唯一键,比如用户名、手机号。
- 要验产品策略:允许复用则需 partial unique index(仅未删除唯一);不允许则提示已存在。测试 case 必须覆盖删后再注册/再创建场景。
金额字段用 float 有什么问题?测试金额精度要注意什么?
👔 Raina面试官: 金额用 float 有啥问题?测金额精度你要盯什么?
🙋 候选人:
- float/double 是二进制浮点,无法精确表示很多十进制小数,累加、乘折扣后容易出现 0.01 偏差,金融场景应使用 DECIMAL/NUMERIC。
- 测试要点:边界金额 0.01、9999999.99;多行明细 sum 是否等于订单 total;折扣、优惠券叠加后四舍五入规则;退款部分退是否按原路精度;跨币种换算末位处理。
- 还要测接口 JSON 里金额是字符串还是数字、前端展示是否二次四舍五入。缺陷常出在 19.9 * 3 不等于 59.7 这类路径,我会用 SQL 聚合对比接口返回值。
👔 Raina面试官: 0.1 + 0.2 这种经典 case 要测吗?
🙋 候选人:
- 要,作为冒烟级精度探针,尤其在语言层仍用 float 的老系统。
- 更贴近业务的是:满减门槛差 0.01 是否生效、分账后各方之和是否等于总额。发现差 1 分先查存储类型和 rounding mode,再查是 bug 还是银行家舍入规则。
时区、夏令时、跨日边界对数据测试有什么影响?
👔 Raina面试官: 时区、夏令时、跨日边界,对数据测试有啥影响?
🙋 候选人:
- 时间字段若混用本地时间和 UTC,查询边界和统计口径会错位,跨日、跨月、跨 DST 切换日最容易出 bug。
- 典型问题:报表按天统计,UTC 存库但前端按东八区筛今天,凌晨订单被划到昨天;夏令时当天少/多一小时,定时任务重复或跳过;有效期 end_time 23:59:59 与 00:00:00 闭开区间。
- 测试会固定时区环境(如 Asia/Shanghai),构造边界时刻数据:23:59:59、00:00:00、月末最后一天、DST 切换日。断言列表筛选、日活、对账结果与 DB 在同一时区语义下一致。
👔 Raina面试官: 怎么造跨日测试数据比较方便?
🙋 候选人:
- 直接 UPDATE 库表时间戳到边界值,或 mock 系统时钟(仅 test env)。
- 同时记录存库是 timestamp with time zone 还是 naive datetime——后者跨国部署必踩坑。接口返回要带时区或统一 ISO8601,避免前端自行猜。
Redis 缓存常见测试点有哪些?(击穿、穿透、雪崩了解吗?)
👔 Raina面试官: Redis 缓存测试你会盯哪些?击穿、穿透、雪崩了解吗?
🙋 候选人:
- 功能上验缓存命中、失效、与 DB 一致性;异常上理解三种经典问题并设计代表 case。
- 穿透:查不存在 key,请求直打 DB——测空值缓存、布隆过滤器是否生效。击穿:热点 key 过期瞬间并发打穿 DB——测互斥锁/逻辑过期是否保护。雪崩:大量 key 同时过期——测 TTL 随机抖动、降级限流。
- 日常还要测:更新 DB 后缓存是否失效或双写一致;Redis 宕机是否降级读库;序列化字段变更后旧缓存是否脏读。压测配合观察 DB QPS spike。
👔 Raina面试官: 缓存和数据库不一致你怎么测?
🙋 候选人:
- 走写后读路径:改 DB → 立即读接口(走缓存)→ 对比 DB 直连值。
- 覆盖 update、delete、批量 job 改数后是否 invalidate。允许短暂不一致的要验最终一致时间和用户可见行为,而不是只测 happy path 命中缓存。
如何对比接口返回数据和数据库落库是否一致?
👔 Raina面试官: 接口返回的数据怎么和库里落库的对上?
🙋 候选人:
- 标准做法是同一业务主键做三方对比:请求参数 → 接口响应 → DB 查询结果,字段映射表要事先对齐。
- 步骤:调接口拿 order_id 等关键键;用 SQL 按主键/外键查主表和关联表;逐字段比——注意枚举码 vs 展示文案、时间格式、金额精度、NULL vs 缺字段。写操作后再读 GET 接口,确认不是只写了库但返回旧缓存。
- 自动化可在 teardown 里 JDBC/ORM 查库断言;复杂对象用 JSON path 对应列名。脱敏字段(手机号中间四位)要按规则比,不要强求全等。
👔 Raina面试官: 异步落库怎么验?
🙋 候选人:
- 用轮询 + 超时,不是 sleep 固定秒数就断言。
- 调接口后轮询 DB 直到状态到达终态或超时失败;MQ 消费、对账 job 场景要验最终一致。记录中间态是否对外可见,避免用户看到半成品数据。
元素定位策略有哪些?id、xpath、css 你会怎么选?
👔 Raina面试官: UI 自动化里元素定位策略挺多的,id、xpath、css 这些你怎么选?
🙋 候选人:
- 我的原则是优先稳定、唯一、语义化的定位器,能用 id/name 就不用 xpath。
- 常见策略:id 最快最稳;css 简洁、性能好,适合 class/属性组合;xpath 最灵活,能走文本和层级,但慢且易脆。name、data-testid、link text 也是好选择——很多团队会推动前端加 testid。
- 选型顺序:data-testid > id > css > xpath。xpath 只在 css 搞不定时用,避免绝对路径和索引依赖。
👔 Raina面试官: 动态 id 比如带时间戳,怎么办?
🙋 候选人:
- 换相对稳定的属性:data-*、aria-label、父级 css + 文本组合。
- 长期推动前端给关键元素加 testid,比维护复杂 xpath 成本低得多。
显式等待、隐式等待、强制等待有什么区别?你怎么用?
👔 Raina面试官: 显式等待、隐式等待、强制等待,这三个到底啥区别?实际怎么用?
🙋 候选人:
- 核心区别:隐式是全局默认等,显式是条件满足才继续,强制是死等 sleep。
- 隐式等待:driver 级别设一次,findElement 找不到就轮询直到超时——简单但不够精准,和显式混用容易算乱超时。显式等待:WebDriverWait + ExpectedCondition,等元素可见/可点击/文本出现,推荐主力用法。强制等待:Thread.sleep/time.sleep,不管页面状态硬等——只作最后手段。
- 我的规范:默认不用隐式或设很短;业务步骤用显式等待;禁止大段 sleep,Playwright 的 auto-wait 也是这个思路。
👔 Raina面试官: Ajax 加载慢,显式等待超时了怎么办?
🙋 候选人:
- 先查等错了条件——可能元素在 DOM 里但还不可交互。
- 改用 visibility_of_element_located 或自定义条件;必要时配合 network idle;超时设合理值并附截图日志,别一味加长 timeout。
