阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 不写单元测试(“测试是 QA 的事”)

不写单元测试(“测试是 QA 的事”)

作者:陈川 阅读数:47379人阅读 分类: 前端综合

单元测试?那是 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 };
}

“灵活”之处:

  • ab 可以是任何东西;
  • 测试时要考虑 a=nullb=undefineda=123 等情况;
  • 后人接手时,先花一周猜参数类型。

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌