单元测试编写

As software developers we all know how important it is to unit test the code that we write. Some of us write tests that verify the happy paths only (bad) and others look for high code coverage numbers. But how many of you are actually writing thorough tests? Let’s take a look at what this means.

作为软件开发人员,我们都知道对所编写的代码进行单元测试的重要性。 我们中的一些人编写的测试仅验证(不正确的)快乐路径,而另一些人则寻找较高的代码覆盖率数字。 但是实际上你们当中有多少人在编写全面的测试? 让我们看看这意味着什么。

Thorough - Test normal & failure conditions, invalid inputs, and boundary conditions.

彻底-测试正常和故障条件,无效输入和边界条件。

Repeatable - Tests must always give you the same results every time so avoid depending on things that might change such as an external server.

可重复-测试每次都必须始终为您提供相同的结果,因此请避免依赖可能发生变化的事物(例如外部服务器)。

Focused - Tests should exercise one specific aspect of your code at a time. A failure in a unit test should lead you to an actual bug in your code.

重点突出-测试应该一次练习代码的一个特定方面。 单元测试失败会导致您在代码中遇到实际错误。

Verifies Behavior - Tests should test behavior without making assumptions on implementations. Avoid over mocking with Mockito.

验证行为-测试应在不对实现进行假设的情况下测试行为。 避免与Mockito过度嘲笑。

Fast - Tests should be fast since 70% of your tests should consist of unit tests.

快速-测试应该快速,因为70%的测试应该包含单元测试。

Concise - Tests should be easy to understand and be a clear blueprint of what the code under test is doing.

简洁-测试应该易于理解,并且是被测代码正在做什么的清晰蓝图。

测试1:不可重复 (Test 1: Not Repeatable)

Above we see a test that is testing SomeClass#getCurrentMonthString. Way too often I see this mistake made during code reviews and it violates the repeatability characteristic. The reason is the default locale, timezone, and system time are being used. This means 1 month from now this test will return March instead of February which will instantly begin failing.

在上方,我们看到一个测试SomeClass#getCurrentMonthString的测试。 我经常看到此错误是在代码审查期间犯的,它违反了可重复性特征。 原因是使用了默认语言环境,时区和系统时间。 这意味着从现在开始的1个月内该测试将返回3月而不是2月,而2月将立即开始失败。

Let’s see how this same test looks with these issues fixed.

让我们看看修复了这些问题后的测试结果。

Here we can see we preset the timezone, locale, and timestamp so that we obtain consistent results.

在这里,我们可以看到我们预设了时区,语言环境和时间戳,以便获得一致的结果。

测试2:不快速+可重复+彻底 (Test 2: Not Fast + Repeatable + Thorough)

This test just hurts me to look at. First off it’s doing network io in an actual unit test. Unit tests should be hermetic and mock network io so you mock responses and error conditions (401/503/200) to make sure your code handles every possibility.

这个测试让我难以接受。 首先,它是在实际的单元测试中进行网络io。 单元测试应该是封闭的并且模拟网络io,因此您可以模拟响应和错误条件(401/503/200),以确保您的代码能够处理所有可能性。

It includes a sleep statement with some magical expectation that every time it’s run it will only take 10s to finish the network call. Please don’t use sleep statements EVER.

它包含一个睡眠声明,并带有一些神奇的期望,即每次运行它只需10秒钟即可完成网络通话。 请永远不要使用睡眠语句。

It’s also testing a method that performs some work asynchronously. Tests should always test against synchronous code.

它还正在测试一种异步执行某些工作的方法。 测试应始终针对同步代码进行测试。

测试3:不彻底 (Test 3: Not Thorough)

Let’s assume we have a calculator class that provides addition, subtraction, multiplication, and division.

假设我们有一个提供加,减,乘和除的计算器类。

Here we have two test functions for addition and subtraction. Each test has verified the core function is working as intended.

这里我们有两个加减法测试功能。 每个测试均已验证核心功能是否按预期工作。

While this will tick the checkbox for increased code coverage it’s clearly violating the thorough characteristic. You can’t just test the happy paths. You have to be extremely thorough and think of every possible way you can break your code and write tests accordingly. You should be adding two positive numbers, adding a positive & a negative number, a negative and a negative number, etc. You get the picture. Do not just test a single condition and move on. That’s not going to keep bugs from showing up in production code.

尽管这将选中复选框以增加代码覆盖率,但它显然违反了全面的功能。 您不能仅仅测试幸福的道路。 您必须非常透彻,并考虑各种可能的方式来破坏代码并相应地编写测试。 您应该添加两个正数,添加一个正数和一个负数,一个负数和一个负数,等等。 不要只是测试一个条件并继续前进。 这不会阻止错误出现在生产代码中。

测试4:不验证行为 (Test 4: Not Verifying Behavior)

Here we have a custom EditText view that overrides the setText() function and prepends “vm-” to anything passed in. Let me explain why this is a bad test and why you should avoid Mockito.verify(). The common thinking here is that since EditText comes with Android then it has it’s own unit tests already so we don’t need to verify that it’s working.

在这里,我们有一个自定义的EditText视图,该视图将覆盖setText()函数,并在传入的任何内容前加上“ vm-”。让我解释一下为什么这是一个不好的测试,以及为什么应该避免使用Mockito.verify()。 这里的普遍想法是,由于EditText是Android附带的,因此它已经具有自己的单元测试,因此我们不需要验证其是否正常工作。

Let’s say 6 months down the road someone wants to introduce a new parent class named CleanupEditText and one of its jobs is to strip out dashes from any input string. In this example with only a few lines of code it’s very easy to see where I’m going with this but imagine this class has 1000+ lines of code. Now the dev changes the parent class of MyEditText to this new class and runs all the tests to verify he hasn’t broken anything. The test that was written for MyEditText passes because all it is doing is verifying that the parent instance of setText() was called.

假设六个月后有人要引入一个名为CleanupEditText的新父类,其工作之一就是从任何输入字符串中去除破折号。 在这个只有几行代码的示例中,很容易看到我要去哪里,但是可以想象这个类有1000多行代码。 现在,开发人员将MyEditText的父类更改为这个新类,并运行所有测试以确认他没有破坏任何东西。 为MyEditText编写的测试通过了,因为它所做的只是验证是否调用了setText()的父实例。

Now we’ve broken the expected behavior and have no way of knowing because the above test is not verifying behavior. It is only verifying a method is being called.

现在,我们已经破坏了预期的行为,并且无法知道,因为上述测试并未验证行为。 它只是在验证一种方法正在被调用。

Here is that same test fixed so it verifies behavior.

这是固定的同一测试,因此可以验证行为。

How easy was that? Yet it’s so instinctive to reach for Mockito.verify() and abuse it without thinking of the possible consequences.

那有多容易? 但是,到达Mockito.verify()并滥用它而不考虑可能的后果是非常本能的。

测试5:不专心 (Test 5: Not Focused)

Now let’s assume we have a class named Calculator again with basic mathematical operations supported.

现在,我们假设我们又有了一个名为Calculator的类,它支持基本的数学运算。

Now someone writes a single test function called testOperations as shown below.

现在,有人编写了一个称为testOperations的测试函数,如下所示。

We should ensure we are identifying units of code and testing those separately otherwise you end up with an integration test as shown above. Remember, this article is about improving your unit tests and unit tests test business logic in isolation.

我们应该确保确定代码单元并分别测试它们,否则您将进行如上所示的集成测试。 请记住,本文是关于改进单元测试和单元测试独立测试业务逻辑的。

Here we have the same test broken up into 3 focused unit tests that are each testing only a single aspect of your code. The test function names have also been modified to more clearly explain what is being tested, with what inputs, and expected result.

在这里,我们将同一测试分为3个重点单元测试,每个单元测试仅测试代码的一个方面。 测试功能名称也已修改,以更清楚地说明正在测试的内容,输入的内容以及预期的结果。

测试6:不简洁+彻底 (Test 6: Not Concise + Thorough)

Here we have a class named AnnualPayCalculator that computes an annual pay given hourly pay and total weekly hours worked.

在这里,我们有一个名为AnnualPayCalculator的类,该类根据给定的小时工资和每周工作总小时数计算年工资。

Below you’ll see a test function that verifies the expected result is returned.

在下面,您将看到一个测试函数,用于验证是否返回了预期的结果。

The main concern here is this test is not concise. It’s way too verbose and requires you to really read the test to understand what’s being tested.

这里主要关注的是这个测试不够简洁。 它太冗长,需要您真正阅读测试以了解所测试的内容。

Here is the same test written more concisely.

这是同样简洁的测试。

测试命名 (Test Naming)

This brings us to our last characteristic of a good unit test that was not called out previously. Naming.

这将我们带到了以前没有提到过的良好单元测试的最后一个特征。 命名。

This is sure to be controversial because on one hand you are used to writing shorter function names in production code.

这肯定会引起争议,因为一方面您习惯于在生产代码中编写较短的函数名称。

But, for test functions, there’s a crucial factor that changes the equation: you never write calls to test functions. A developer types out a test name exactly once — in the function signature. Given this, brevity still matters, but it matters less than in production code.

但是,对于测试函数,有一个改变方程式的关键因素:您永远不会编写对测试函数的调用 。 开发人员只需在函数签名中输入一次测试名称即可。 鉴于此,简洁仍然很重要,但是它比生产代码中的重要性要小。

Whenever a test breaks, the test name is the first thing you see, so it should communicate as much as possible.

每当测试失败时,您都会首先看到测试名称,因此它应该尽可能多地传达信息。

Format:

格式:

when_expectedwhen_with_expected

Bad examples:

错误的例子:

testOnActivityCreatedtestGetHashedAttachmentFilenames

Good examples:

很好的例子:

viewCreated_listViewExistsgetHashedAttachmentFilenames_withNullList_emptyStringReturned

摘要 (Summary)

  • Don’t just write unit tests. Include integration and workflow where needed. Don’t waste time on these if they aren’t absolutely necessary to cover something that isn’t already being tested.不要只是编写单元测试。 在需要时包括集成和工作流程。 如果不是绝对不需要涵盖尚未经过测试的内容,请不要在这些内容上浪费时间。
  • Make sure your tests follow the characteristics of a good unit test确保您的测试遵循良好的单元测试的特征
  • Name your tests properly正确命名测试
  • A failure in a test should immediately tell you exactly what is broken and under what condition测试失败应立即告诉您什么地方坏了,在什么情况下
  • Always strive to test functionality/behavior. Verifying a method is called only should be rarely used始终努力测试功能/行为。 验证方法仅被调用应该很少使用

翻译自: https://medium.com/swlh/writing-thorough-unit-tests-591292d5a571

单元测试编写


http://www.taodudu.cc/news/show-5875223.html

相关文章:

  • JWT登录工具类及单元测试
  • golang mysql 单元测试_golang 之单元测试
  • golang单元测试框架实践
  • Junit单元测试总结
  • 老师教我们用计算机画画,感恩老师的广播稿200字
  • 白杨SEO:SEO网站代码优化有哪些?如何做才能更符合百度搜索引擎优化?
  • 搜索引擎优化教程_编程入门自学教程_菜鸟教程-免费教程分享
  • ubuntu 1604 random: crng init done 后无反应
  • 解决make: Nothing to be done for的方法
  • 解决Canceled future for execute_request message before replies were done
  • layui table done与templet
  • $.ajax() 中 done() 、fail()、always() 的用法
  • golang context的done和cancel的理解 for循环channel实现context.Done()阻塞输出
  • avue.js:done is not a function
  • IQKeyboardManager Done 修改为 完成
  • layui之laydate日期组件在done中重新渲染
  • turtl函数
  • done后面接重定向文件
  • jquery deferred done then区别
  • 关于vb2_buffer_done
  • UVM中item_done的作用?
  • imx6ull uboot nfs Loading* done异常
  • Shell中while循环的done 后接一个重定向
  • jquery 中$.ajax().done() 的用法
  • 连通域计算
  • 连通域分析
  • matlab 连通域分割,基于OpenCV.Net连通域分析进行文本块分割
  • 连通域分析之种子填充法
  • 寻找连通域C++程序复现(个人C++学习记录)
  • 解密英文藏头诗C语言,《C语言指针进阶》PPT课件.ppt

单元测试编写_编写详尽的单元测试相关推荐

  1. python hello world程序编写_编写高质量代码 改善Python程序的91个建议

    建议1:理解Pythonic概念 建议2:编写Pythonic代码 建议3:理解Python与C语言的不同之处 建议4:在代码中适当添加注释 建议5:通过适当添加空行使代码布局更为优雅.合理 建议6: ...

  2. 断言工具的编写_编写干净的测试–用特定领域的语言替换断言

    断言工具的编写 很难为干净的代码找到一个好的定义,因为我们每个人都有自己的单词clean的定义. 但是,有一个似乎是通用的定义: 简洁的代码易于阅读. 这可能会让您感到有些惊讶,但我认为该定义也适用于 ...

  3. maven插件编写_编写Maven插件的提示

    maven插件编写 最近,我花了很多时间为Maven编写插件或在其中工作. 它们简单,有趣且有趣. 我以为我会分享一些技巧,使编写它们时的生活更轻松. 提示1:将任务与Mojo分开 最初,您将把moj ...

  4. 程序设计文档编写_编写有效的设计系统文档的6个技巧

    程序设计文档编写 重点 (Top highlight) I wrote this article to document what I'm learning professionally while ...

  5. python自动化测试脚本怎么编写_编写自动化测试脚本心得---菜鸟入门篇

    编写自动化测试脚本心得 -------- 菜鸟入门篇 本文中将不会讲解 ISEE 的测试原理.不说明 Python 的常用语法.不介绍 OTP 测试平 台的架构, 自动化测试组的牛人们已经为我们编写了 ...

  6. 服务器编写_编写下载服务器。 第六部分:描述您发送的内容(内容类型等)...

    服务器编写 就HTTP而言,客户端下载的只是一堆字节. 但是,客户真的很想知道如何解释这些字节. 它是图像吗? 还是ZIP文件? 本系列的最后一部分描述了如何向客户端提示她下载的内容. 设置 内容类型 ...

  7. java单元测试内存数据库_基于内存数据库的单元测试

    背景: 当我们在进行单元测试时,对于关系型数据库(例如mysql)和非关系型数据库(例如redis)的处理,有的小伙伴通过mock的方式制作出假的数据进行测试,有的小伙伴会连到开发环境操作数据库.而连 ...

  8. java 单元测试 异步_使用Moq模拟单元测试的异步方法

    我正在测试一个用于进行Web API 调用的服务的方法 . 如果我还在本地运行Web服务(位于解决方案中的另一个项目中),则使用普通 HttpClient 可以正常进行单元测试 . 但是,当我签入我的 ...

  9. 对编写的代码进行单元测试_编写数据访问代码测试–单元测试是浪费

    对编写的代码进行单元测试 几年前,我是为我的数据访问代码编写单元测试的那些开发人员之一. 我正在孤立地测试所有内容,我对自己感到非常满意. 老实说,我认为自己做得很好. 哦,男孩,我错了! 这篇博客文 ...

最新文章

  1. AI工程师必读的10本ML读物(附PDF下载)
  2. inc指令是什么意思_mips指令集与cpu架构(一)
  3. 《大数据原理:复杂信息的准备、共享和分析》一一2.5 在标识符中嵌入信息:不推荐...
  4. 29 Python - 字符与编码
  5. SEO的十种赚钱方式
  6. python狗图像识别_TensorFlow卷积神经网络之使用训练好的模型识别猫狗图片
  7. java 课程设计数据库_人事管理系统(java数据库课程设计)+SQL数据库
  8. 卸任后的马云“忙”坏了,健美大赛、蹦迪、修空调、种蘑菇,真相看懵了
  9. C++ 一篇搞懂继承的常见特性
  10. 终于有人把联邦学习讲明白了
  11. 深度学习_深度学习基础知识_二分类、单标签多分类、多标签多分类、多任务的含义
  12. 通向大规模医疗知识图谱:万字详解天衍实验室知识图谱对齐技术
  13. 数据库 之 round函数
  14. Java博客项目(重点)
  15. Python使用Pillow库进行图像
  16. 人脸识别之人脸对齐(一)--定义及作用
  17. java sop_JAVA开发环境搭建SOP.doc
  18. SAR ADC上极板采样浅谈
  19. 易助工资总额管控发版说明
  20. 如果汉朝有RPA,那么李陵就能枭首10万匈奴,大汉版图扩至地中海

热门文章

  1. RNA二级结构在 siRNA设计中的应用
  2. 【自然语言NLP】TensorFlow使用LSTM实现情感分析任务
  3. 也说TCP/IP之计算机网络发展史(一)
  4. Windows本地配置Nginx
  5. Python生成依赖包文件requirements.txt并下载安装
  6. Jenkin发布PHP代码配置
  7. 近期靠谱EI会议——移动互联网、云计算与信息安全国际学术会议(MICCIS 2023)
  8. 蓝云ERP系统项目笔记——登录与密码管理(4)
  9. 免费搜索引擎登录入口
  10. Websocket 状态码