不写单元测试(“测试是 QA 的事”)
单元测试?那是 QA 的事,关我什么事? 代码能跑就行,测试是测试团队的工作,写单元测试只会拖慢开发进度。如果你也这么想,恭喜你,你已经掌握了“防御性编程”的精髓——如何让代码变得难以维护。以下是几种经典操作,保证让你的同事和未来的自己抓狂。
拒绝单元测试的“优雅”姿势
1. 直接调用生产环境接口
为什么要在测试环境模拟数据?直接调用生产环境接口多省事!比如,写一个用户登录功能,直接调生产环境的登录接口,连 Mock 都省了:
async function login(username, password) {
const response = await fetch('https://production-api.com/login', {
method: 'POST',
body: JSON.stringify({ username, password }),
});
return response.json();
}
这样做的“好处”是:
- 测试时可能把生产数据库搞崩;
- 每次测试都要输入真实账号密码,方便“安全测试”;
- 如果接口挂了,你的测试也挂了,一举两得。
2. 逻辑和 UI 强耦合
把业务逻辑和 UI 混在一起写,让测试无从下手。比如,一个按钮点击后直接修改 DOM 并发送请求:
document.getElementById('submit-btn').addEventListener('click', () => {
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
fetch('https://api.com/login', {
method: 'POST',
body: JSON.stringify({ username, password }),
})
.then(response => response.json())
.then(data => {
document.getElementById('result').innerHTML = `欢迎, ${data.user.name}!`;
})
.catch(() => {
document.getElementById('result').innerHTML = '登录失败!';
});
});
这种代码的“优势”:
- 无法单独测试登录逻辑,必须启动整个页面;
- UI 改动直接导致测试失败;
- 想写单元测试?先学会用 Puppeteer 吧!
3. 依赖全局状态
让函数的行为完全依赖全局变量,确保测试时状态混乱。比如:
let isLoggedIn = false;
function toggleLogin() {
isLoggedIn = !isLoggedIn;
console.log(`当前登录状态: ${isLoggedIn}`);
}
测试这段代码时,你需要:
- 手动重置
isLoggedIn
; - 祈祷没有其他测试用例修改它;
- 享受“测试顺序影响结果”的随机惊喜。
4. 不处理边界情况
边界情况?那是用户的问题。比如,写一个计算价格的函数:
function calculatePrice(quantity, price) {
return quantity * price;
}
“优雅”之处在于:
- 用户传
quantity = -1
?返回负数价格,让财务崩溃; - 用户传
price = 'abc'
?返回NaN
,让前端展示“NaN 元”; - 测试?不存在的,用户会帮你测出所有 Bug。
5. 用“魔数”代替常量
直接在代码里写死数字或字符串,让维护者猜你的意图。比如:
function getDiscount(price) {
if (price > 1000) {
return price * 0.1; // 0.1 是什么?谁知道呢
}
return 0;
}
“高级”技巧:
- 不要写注释,让后人自己琢磨;
- 修改折扣时,记得全局搜索
0.1
; - 测试覆盖率?这种代码根本测不完。
让测试工具无从下手的“黑科技”
1. 使用随机数
在核心逻辑里插入随机行为,让测试结果不可预测:
function shouldOfferDiscount() {
return Math.random() > 0.5; // 50% 概率打折,惊喜吧!
}
测试这种函数时:
- 第一次跑测试通过,第二次失败;
- 用
jest.spyOn(Math, 'random')
?太麻烦了,放弃吧; - 最终报告里写“测试通过率 50%”。
2. 依赖外部时间
让函数的行为依赖当前时间,比如:
function isPromotionAvailable() {
const hour = new Date().getHours();
return hour >= 20; // 晚上 8 点后促销
}
测试时你需要:
- 手动修改系统时间;
- 用
jest.useFakeTimers()
?太复杂了; - 深夜加班测试,享受“时间同步”的乐趣。
3. 副作用满天飞
让函数偷偷修改外部状态,比如:
const userCache = {};
function getUser(id) {
fetch(`https://api.com/users/${id}`)
.then(response => response.json())
.then(data => {
userCache[id] = data; // 悄悄修改缓存
});
}
这种代码的“魅力”:
- 测试
getUser
时,userCache
突然变了; - 无法通过输入输出验证函数行为;
- 测试用例之间相互污染,刺激如俄罗斯轮盘赌。
终极奥义:让后人不敢动你的代码
1. 写“自毁”代码
在代码里埋下定时炸弹,比如:
function processPayment(amount) {
if (amount > 10000) {
throw new Error('金额过大,疑似黑客攻击!');
}
// 真实支付逻辑
}
“保险”措施:
- 测试大额支付?直接报错;
- 后人不敢改逻辑,生怕触发“安全机制”;
- 线上出问题?一定是测试用例没覆盖到。
2. 使用“超动态”逻辑
用 eval
或动态属性名,让静态分析工具崩溃:
function getConfigValue(key) {
return eval(`config.${key}`); // 谁敢重构?
}
“动态”优势:
- 无法用 IDE 跳转到定义;
- 测试时不知道
key
有哪些可能值; - 代码安全扫描工具会疯狂报警,增加安全感。
3. 拒绝文档和类型
不写 JSDoc、不用 TypeScript,让后人“自由发挥”:
function mergeData(a, b) {
return { ...a, ...b };
}
“灵活”之处:
a
和b
可以是任何东西;- 测试时要考虑
a=null
、b=undefined
、a=123
等情况; - 后人接手时,先花一周猜参数类型。
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn