测试驱动开发 测试前移_我如何以及为什么认为测试驱动开发值得我花时间

测试驱动开发 测试前移

by Ronauli Silva

通过罗纳利·席尔瓦(Ronauli Silva)

I first read about test driven development (TDD) in some technical reviews blog, but I barely read it (or thought about it). Why would people write tests first when they already knew the logic?

我首先在一些技术评论博客中阅读了有关测试驱动开发(TDD)的信息,但几乎没有阅读(或考虑过)。 人们为什么已经知道逻辑就为什么要先写测试

So what was this all about? Writing tests first, incrementally building the logic, and doing it in iterations. The funny thing is, when you give two programmers five minutes to code a simple fibonacci sequence and ask one to do TDD, by the end of the 5 minutes, the programmer doing TDD may say “I have test for it!” But they won’t have finished the code. On the other hand, the other one will have finished the entire fibonacci sequence and will have optimized it.

那到底是什么呢? 首先编写测试,逐步构建逻辑,然后进行迭代。 有趣的是,当您给两个程序员五分钟的时间来编写一个简单的斐波那契序列并要求一个人进行TDD时,在5分钟结束时,执行TDD的程序员可能会说:“我已经对此进行了测试!” 但是他们不会完成代码。 另一方面,另一个将完成整个斐波那契数列并对其进行优化。

为什么要使用TDD? 单元测试不够好吗? (Why use TDD? Aren’t unit tests good enough?)

At the end of last year, I finally met TDD face to face. In a three-month bootcamp session, we were forced to always do things with TDD. I was already struggling enough, and so my brain always rebelled when it came time to write the tests.

去年年底,我终于与TDD面对面了。 在为期三个月的训练营会议中,我们被迫始终使用TDD进行操作。 我已经很挣扎了,所以到了编写测试的时候,我的大脑总是反叛。

Why should we write tests first when I can directly code the logic, my brain asked? Can’t we just write them later? After all functionality is finished?

我的大脑问,当我可以直接编写逻辑代码时,为什么要先编写测试? 我们不能稍后再写吗? 所有功能完成之后?

Let me give you a quick overview of TDD in a nutshell.

让我简要概述一下TDD。

Let’s say I’m creating a fibonacci function. I might ask, what is the simplest assertion on a fibonacci? => Returns 1 if input is 1.

假设我要创建一个斐波那契函数。 我可能会问,关于斐波那契的最简单的断言是什么? =>如果输入为1,则返回1。

What is the simplest solution for that assertion? The simplest solution, I mean it.

该断言最简单的解决方案是什么? 最简单的解决方案 我是认真的。

Now, next move. What is next simplest assertion for fibonacci?=> Returns 2 for inputs = 3

现在,下一步。 斐波那契的下一个最简单的断言是什么?=>输入2返回2 = 3

Again, let’s fix this very quickly. Just return it and add some branching.

同样,让我们​​快速修复此问题。 只需返回它并添加一些分支即可。

Move to another expectation. Aim for a bigger number. Do it iteratively, incrementally.

移到另一个期望。 争取更大的数量。 逐步进行迭代。

On and on it goes, until you get the nice solution for your fibonacci function. If you want to practice more, try adding memoization during the process (and don’t forget—with TDD).

不断进行下去,直到您获得斐波那契函数的理想解决方案为止。 如果您想练习更多,请尝试在此过程中添加备忘(不要忘了-使用TDD)。

Did you notice what we did there? The baby steps, your assertion, and how we define the solution? Your thought process got separated into these five critical points:

您注意到我们在那里做了什么吗? 婴儿的脚步,您的主张以及我们如何定义解决方案? 您的思考过程分为以下五个关键点:

Simple & Incremental Design — You have to think about what is the simplest thing a particular function could do, and what’s coming next. The fibonacci example describes this point perfectly.

简单和增量设计-您必须考虑某个特定功能可以做的最简单的事情,以及下一步的工作。 斐波那契示例很好地描述了这一点。

Assertion — What is your expectation of that function? And how do you describe that expectation? Will other people understand it quickly?Some test libraries provide you with a test description feature. That string is the only verbose thing that explains what your code is doing.

断言-您对该功能有什么期望? 您如何描述这种期望? 其他人会很快理解吗?某些测试库为您提供测试描述功能。 该字符串是解释您的代码正在执行的唯一冗长的操作。

Make sure it’s a good explanation, or you’ll get a call on your holiday because your unreadable test case is failing, and no one knows why.

确保这是一个很好的解释,否则您的假期会打来电话,因为您无法读取的测试用例失败了,没人知道原因。

Testable Design — How should you design it so it can be testable? Take a look at these two snippets below.

可测试的设计 -应该如何设计它以便可测试? 看看下面的这两个片段。

The first one:

第一个:

By doing TDD, since you write the test first, you have to make sure that your code is testable. You can see from the example that you don’t even test your fibonacci function. Instead, you test the side-effect of that fibonacci logic in your code, which invokes the console.log function.

通过执行TDD,由于您首先编写了测试,因此必须确保您的代码是可测试的 从示例中可以看到,您甚至没有测试斐波那契函数。 而是在代码中测试该斐波那契逻辑的副作用 ,该逻辑调用console.log函数。

The other thing is, you never know which one is failing, the console.log() or your fibonacci block when you refactor it. In this way, TDD leads us to increase modularity in our code.

另一件事是,当您重构它时,您永远都不知道哪个是失败的console.log()或您的fibonacci块。 通过这种方式,TDD使我们提高了代码的模块化程度。

Now, let’s look at second snippet.

现在,让我们看看第二个片段。

In the second example, we can see that we test the particular fibonacci function, not the other function that spikes on it. We are confident that the function works perfectly under the conditions that we state. We are sure that if the other function invokes our fibonacci and fails, it is not from our code.

在第二个示例中,我们可以看到我们测试了特定的斐波那契函数,而不是其他尖峰函数。 我们相信该功能在我们声明的条件下可以完美运行。 我们确定如果另一个函数调用我们的斐波那契并失败,则不是来自我们的代码。

Negatives and Corner Cases — what do you expect when something’s not right: is it invoked with null? Does it throw an exception? How should it be handled? What could possibly happen in the code? What could be the strangest and weirdest thing that could happen in this loop? What test can catch that?

否定情况和极端情况 –如果出现不正确的情况,您会期望什么:使用null调用吗? 它会引发异常吗? 应该如何处理? 代码中可能会发生什么? 在此循环中可能发生的最奇怪和最奇怪的事情是什么? 有什么考验可以抓住?

Boundaries — Should you expect that from your function? Are you sure it’s not another class’s responsibility?

边界 -您是否应该从职能中获得期望? 您确定这不是另一堂课的责任吗?

我对TDD的问题 (My issues with TDD)

Yes, it is slow indeed. Sometimes, your time is doubled since you’re writing both tests and logic at the same time. This makes how you use your keyboard important (typing speed, better shortcut usage, and so on).

是的,确实很慢。 有时,由于您同时编写测试和逻辑,因此您的时间增加了一倍。 这使您使用键盘的方式变得很重要(键入速度,更好的快捷方式用法等)。

And even worse —when the requirements change—you have to refactor or delete and rewrite test code you worked hard on. Which means that tests code is code you write that is more likely to be deleted in the future. And you are doing it, iteratively. DELETES. CODES. REWRITES. AGAIN. IN A LOOP!

更糟糕的是,当需求发生变化时,您必须重构或删除并重写您一直在努力的测试代码。 这意味着测试代码是您编写的代码,将来很有可能被删除。 而您正在迭代地这样做。 删除。 编码。 重写。 再次。 一圈!

Think about it. Why would you write code that is more likely to be deleted?

想一想。 您为什么要编写更有可能被删除的代码?

“Nope, that’s enough of this TDD thing. I’ll do it when I find a strong reason why I should spend time writing code I’m likely to delete”, I said to myself.

“不,这个TDD够了。 我对自己说:“当我发现有充分的理由为什么我应该花时间编写可能会删除的代码时,我会做的。”

And that was right before I unconsciously started digging my own grave.

那是在我不知不觉开始挖掘自己的坟墓之前。

为什么我改变主意 (Why I changed my mind)

The enlightenment came about two months later, when I was assigned to a group that did not implement TDD well at all.

大约两个月后,当我被分配到一个完全没有很好地执行TDD的小组时,就得到了启迪。

I mean, they implemented TDD, but they left the tests broken. They didn’t bother to fix those failing test cases (which often broke because the requirements had changed). And this happened because of the most cliche reason in the world: they didn’t have time. They had to make deadlines.

我的意思是,他们实施了TDD, 但是却使测试失败了。 他们没有费心去修复那些失败的测试用例(由于需求发生了变化,测试用例经常失败)。 发生这种情况是由于世界上最陈词滥调的原因:他们没有时间。 他们必须规定最后期限。

After looking at the situation, I mumbled “Look, see! This TDD doesn’t work in the production world!” It made me question many things: is this TDD worth fighting for? Is TDD worth the time? Does it even deliver any business value?

看完情况后,我喃喃地说:“看,看! 该TDD在生产环境中不起作用!” 这让我提出了很多问题:这个TDD是否值得争取? TDD值得吗? 它甚至提供任何商业价值吗?

After a while, I realized that the problems were growing exponentially, tasks were getting delayed, chaos was reigning, and the developer experience was getting really bad — all because they implemented TDD poorly and halfheartedly. It was even worse than not writing tests at all.

过了一会儿,我意识到问题正在成倍增长,任务被延迟,混乱不断,开发人员的经验真的变得很糟糕-所有这些都是因为他们对TDD的执行不力而全力以赴。 比根本不编写测试还要糟糕。

Here are some of the issues it caused:

这是它引起的一些问题:

  • When I added a new feature or refactored things, I didn’t know whether that code was failing or not because the test was already failing.

    当我添加新功能或重构事物时,我不知道该代码是否失败,因为测试已经失败。
  • We were forced to have high threshold on code coverage. And make no mistake, programmers are smart and sneaky. They write tests with no expectations, like smoke tests. And that was the only test they had on that particular logic. It was like, we only knew it was failing after everything was on fire. How dangerous.

    我们被迫对代码覆盖率设置高阈值。 毫无疑问,程序员是聪明而狡猾的 。 他们编写没有期望的测试,例如冒烟测试。 那是他们对该特定逻辑进行的唯一测试。 就像,我们只知道一切都着火之后才失败。 多么危险

  • We used CI/CD for deployment. And we always deployed even though it was failing, which was scary: You never knew whether your production itself was failing, or if it was because you didn’t fix the tests.

    我们使用CI / CD进行部署。 而且,即使失败了,我们也总是进行部署,这很可怕:您永远不知道自己的生产是否失败,或者是因为您没有修复测试。
  • After production, we ended up fixing strange and completely out-of-mind bugs. We had never even thought of those strange conditions before. (Ever find a situation when something in a try-catch block is failing but not throwing an exception?)

    生产后,我们最终修复了奇怪且完全过时的错误。 我们以前从未想过那些奇怪的情况。 (是否找到了try-catch块中的某项失败但没有引发异常的情况?)

Oh, the horror!

哦,恐怖!

After analyzing the situation, doing it in iterations, and reflecting on it, I realized that TDD is actually a golden nugget. If done right, it can make us better developers.

在分析了情况,反复进行并反思之后,我意识到TDD实际上是一个金块。 如果做得对,它可以使我们成为更好的开发人员。

为什么我现在爱TDD (Why I now love TDD)

使用TDD,您的bug更少 (With TDD, you have fewer bugs)

You’ll hardly miss things that you can catch with your tests.

您几乎不会错过可以通过测试掌握的东西

When you get a requirement, you write a test for it first. Then you run the test, and see if it fails first. When you add the logic, you see if it passes.

收到需求后,您首先要为其编写测试。 然后运行测试,然后查看它是否首先失败。 添加逻辑时,您可以查看它是否通过。

Seeing it fail is important, because you know what broke your code. In the long run, this practice ensures that all lines in your code are well-tested.

看到它失败很重要,因为您知道什么破坏了您的代码 。 从长远来看,这种做法可以确保代码中的所有行都经过良好测试。

TDD节省了很多时间(将来) (TDD saves you lot of time (in the future))

CI/CD relies heavily on tests. If you write the wrong tests (or too few tests) you already wasted five hours to find what errors it couldn’t catch. If you write good tests, and spend just five more minutes writing deeper and more complete conditions of your code, you’ll save time debugging it in the future.

CI / CD严重依赖测试。 如果您编写了错误的测试(或测试太少),您已经浪费了五个小时来查找无法捕获的错误。 如果您编写了良好的测试,并且只花了五分钟以上的时间来编写更深入,更完整的代码条件,则可以节省将来调试它的时间。

TDD处理编码的人为方面 (TDD deals with the human aspects of coding)

The main ones being negligence and forgetfulness. If you write all the logic directly, by the end of, say, line 190, you may forget why you multiplied a variable by 100 at line 19.

主要是疏忽和健忘。 如果直接编写所有逻辑,例如在第190行的末尾,您可能会忘记为什么在第19行将变量乘以100。

But, by doing it incrementally and stating the assertion of our code, we gradually build our understanding. This makes us understand the code and its behaviors better.

但是,通过逐步执行并声明代码声明,我们逐渐建立了理解。 这使我们更好地理解了代码及其行为。

As a bonus, we have sort of living and functional documentation of our code. You can see which test is failing if you delete the previous line, and you instantly know why.

值得一提的是,我们还提供了一些有效的代码文档。 如果删除上一行,您可以看到哪个测试失败,并且您立即知道原因。

TDD可帮助您集中精力 (TDD helps you focus)

Programmers tend to write too much code, or write code that does too much. Or they try to plan for conditions that never exist. Often, when my team practiced pair pairing, I discovered that TDD allowed us to write less code compared to other teams that didn’t do TDD. While coding, we were focused on getting the test case passed — nothing less, nothing more.

程序员倾向于写太多的代码,或者写太多的代码。 或者他们试图为不存在的情况做计划。 通常,当我的团队练习配对时,我发现与没有TDD的其他团队相比,TDD允许我们编写更少的代码。 在编码时,我们专注于通过测试用例-没什么,仅此而已。

TDD也有益于您的大脑 (TDD also benefits your brain)

You have proof of your code’s readiness for production, even before deploying it. You don’t have to worry about things you already tested for before. You don’t have to brag to your project manager about how project is going, because you can show them that the tests are passing!

您甚至可以在部署代码之前就证明您的代码已经可以投入生产。 您不必担心之前已经测试过的东西。 您不必向项目经理吹嘘项目的进展情况,因为您可以向他们证明测试已通过!

However, TDD is not always your silver bullet. It takes time. You have to set up the project — such as the environment, mocks, and stubs — even before you start doing anything.

但是,TDD并不总是 你的银弹。 这需要时间。 您必须在开始做任何事情之前就设置项目(例如环境,模拟和存根)。

But remember, time spent on writing tests is not wasted time. It’s the time you invest now to save your time later. It’s the investment you make on the system you build, as you build code on top of more code. And you want to make its foundation as solid as possible. TDD gives you that.

但是请记住,花在编写测试上的时间不会浪费时间。 现在是时候进行投资,以节省以后的时间了。 当您在更多代码之上构建代码时,这就是您对所构建系统的投资。 您想使其基础尽可能牢固。 TDD为您提供。

In the end, it could cost you a fortune if you don’t do TDD. It may take time, but it is good for you and your team in the long run.

最后,如果您进行TDD,可能会花费您一笔巨款。 这可能会花费一些时间,但从长远来看,这对您和您的团队都是有好处的。

翻译自: https://www.freecodecamp.org/news/test-driven-development-i-hated-it-now-i-cant-live-without-it-4a10b7ce7ed6/

测试驱动开发 测试前移

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/394102.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm

对于一个牛,它存在两种状态:1.处于联通分量 2.不处于联通分量。对于处于联通分量的牛,求出联通分量的大小;对于不处于联通分量的牛,求出其距离联通分量的路程联通分量大小。 不同的联通分量,染上不同的颜色…

ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(持续更新中...)

开发工具:VS2015(2012以上)SQL2008R2以上数据库 您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB 升级后界面效果如下: 日程管理 http://www.cnblogs.com/ymnets/p/7094914.html 任务调度系统界面 http://www.cnblogs.com/ymnets/p/5065154.h…

leetcode106. 从中序与后序遍历序列构造二叉树(dfs)

根据一棵树的中序遍历与后序遍历构造二叉树。注意: 你可以假设树中没有重复的元素。例如,给出中序遍历 inorder [9,3,15,20,7] 后序遍历 postorder [9,15,7,20,3] 返回如下的二叉树:3/ \9 20/ \15 7解题思路 根据后序遍历的最后一个元素是父节点&…

【FRDM-K64F学习笔记】使用ARM mbed和Keil MDK下载你的第一个程序

FRDM-K64F开发平台采用MK64FN1M0VLL12微控制器。该控制器包含一个带有浮点单元的ARM Cortex-M4内核。其最高工作频率为120MHz,具有256KB的RAM、1MB闪存以及许多其他外设。它非常适合大多数可以采用以太网、SD卡存储以及板载模拟-数字转换器的IoT应用。但是&#xff…

php 实时更新内容_亿级视频内容如何实时更新?优酷视频背后的技术揭秘

简介: 优酷视频内容数据天然呈现巨大的网络结构,各类数据实体连接形成了数十亿顶点和百亿条边的数据量,面对巨大的数据量,传统关系型数据库往往难以处理和管理,图数据结构更加贴合优酷的业务场景,图组织使用…

ios集成firebase_如何使用Firebase将Google Login集成到Ionic应用程序中

ios集成firebaseby Ryan Gordon通过瑞安戈登(Ryan Gordon) 如何使用Firebase将Google Login集成到Ionic应用程序中 (How to integrate Google Login into an Ionic app with Firebase) A lot of apps these days need to maintain some form of user authentication. This hel…

面向对象三大核心特点,封装、继承和多态

封装 封装其实是一种思想,将事物状态和功能装进一个容器,那么这个容器在python中就是类,由这个类产生的对象都拥有类的属性和功能 在面向对象的思想中,推崇将具有某些共同特征的事物归为一类,那么这些事物就可以看做是…

java编写某计算器控制台程序_用java程序编写一个计算器

点击查看用java程序编写一个计算器具体信息答:给你一个参考,希望不要被百度吞了当晚餐 import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.text.Decimal…

物联网商机迸发 LPWAN芯片现身 本文转自d1net(转载)

联发科技发表首款NB-IoT系统单芯片MT2625。来源:MediaTeK 物联网(IoT)带动的庞大商机吸引各方业者积极投入,尤其是各种联网技术不断现身,争夺各式各样极富发展潜力的应用领域。 根据IDC的调查报告,物联网市场在2017年声势看涨&…

jquery之stop()的用法

工作中遇到过的实际案例: 1、我在项目里做的一个下拉菜单,当鼠标移上去的时候就菜单显示,当鼠标离开的时候菜单隐藏 如果我快速不断地将鼠标移入移出菜单(即,当菜单下拉动画未完成时,鼠标又移出了菜单&…

leetcode1123. 最深叶节点的最近公共祖先(dfs)

给你一个有根节点的二叉树,找到它最深的叶节点的最近公共祖先。 回想一下: 叶节点 是二叉树中没有子节点的节点 树的根节点的 深度 为 0,如果某一节点的深度为 d,那它的子节点的深度就是 d1 如果我们假定 A 是一组节点 S 的 最近…

sed空格替换成回车_【一题试水平】 利用sed命令将test.txt中所有的回车替换成空格?...

题目背景,这个题也很有年头了,看似简单,实则坑很大,good luck! 先不要看答案 看看自己能写出多少方法.方法1 把每一行内容追加到Hold Space中,最后1行弄回到Pattern space中.然后进行替换基础版[rootoldboyedu-show01 …

github 和git_学习编码时如何学习Git和GitHub

github 和gitby Iago Rodrigues通过Iago Rodrigues 学习编码时如何学习Git和GitHub (How you can learn Git and GitHub while you’re learning to code) In this article, I’ll give you some hints about how to become a Git/GitHub ninja. Also, as a bonus, I’ll show…

015_ICMP专项研究监控

一、数据demo cat /proc/net/snmp Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates …

leetcode129. 求根到叶子节点数字之和(dfs)

给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字。例如,从根到叶子节点路径 1->2->3 代表数字 123。计算从根到叶子节点生成的所有数字之和。说明: 叶子节点是指没有子节点的节点。示例 1:输…

java for i i 区别,i ++amp;和i ++之间的区别是什么? ++我在for循环(Java)?

hello, Ive just started learning Java and now Im into for loop statement. I dont understand how i i works in a for loop statement.I mean how they work in mathematics operations like addition and subtraction. I hope some one will explain this to me.解决方案…

php 设置中文 cookie, js获取

参考链接:http://www.nowamagic.net/librarys/veda/detail/1271 http://www.ruanyifeng.com/blog/2008/06/base64.html cookie.js 文件 var Cookies {}; /** * 设置Cookies */ Cookies.set function(name, value){ var argv arguments; var argc arguments.length; var exp…

学会这二十个正则表达式,能让你少些1000行代码!

正则表达式,是一个强大且高效的文本处理工具。通常情况下,通过一段表达准确的表达式,能够非常简短、快速的实现复杂业务逻辑。因此,正则表达式通常是一个成熟开发人员的标配,可以辅助实现开发效率的极强提升。在需要实…

mergesort_Mergesort算法的功能方法

mergesortby Joe Chasinga通过乔查辛加(Joe Chasinga) Mergesort算法的功能方法 (A functional approach to mergesort algorithm) Algorithms are often difficult for people to understand. I believe that this is because they are most often programmed or explained i…

循环内部异步函数处理相关问题解析

需求分析:根据一级标题ID筛选出所有对应的二级标题,返回一级标题ID,标题名和二级标题ID,标题名组成的数组 问题:通过forEach遍历所有一级标题取对应的ID,根据ID条件查找所有的二级标题,遍历符合…