Rails 5 Test Prescriptions 最后一章,如何测试继承下来的代码,legacy code
Set expectations
你不可能把一个老旧的代码野兽只用一晚就转变成优雅的奇迹marvel.你需要如下做法:
- 让自己有好的状态,用15分钟挥舞拳头诅咒之前的程序员
- 开始工作,这个codebase现在归你了。
一上来就给遗产代码增加测试不是好注意,这里有2个原因:
第一个问题是,你接管这个遗产代码后你期望做点什么,而客户的想法未必和你一样。所以先和客户交流,或者和产品经理充分交流,确定需求后再开始。
第二个问题是, 不得不处理 常常的矛盾的遗产代码。遗产代码常常太互相过度依赖或者不好理解,导致难以使用单元测试。除非你先进行重构。但是不经过单元测试就重构更容易导致bugs,特别是你还没有完全理解这些新代码。
这2个问题都导致快速的处理遗产代码是不可能的事情。
工作代码中那些不是十分明确需要改变的代码就别改。如果它运行的很好并且需求也和以前一样,唤醒沉睡的熊(比喻)只能让你远离你的最重要的事。
对于遗产代码,逐步前进,走你能确定的小步。保证自己写的新代码通过测试。当你写新代码时,对现存的代码做小的改进,让总体的代码基础变好。
Getting Started with Legacy Code
做3件事情:
get the code in source control
让代码处于版本控制Source Control。可能它已经处于版本控制,但你应该小心。确认你有所有的存取权利对任何你需要的代码仓库code repository。最好使用Git或者其他版本控制系统让你可以创建和管理branches。这样你可以轻松的通过使用分支来探索源代码的变化,根据需要让scratch pads缓存可以被保存或丢弃。
get the code running
产品环境的设置, 推迁移产品环境到一个更标准的地方。Docker是一个有用的container tools. 可以把产品环境复制到a Docker container.
get the Test Suite running
如果之前的团队不认真的写测试,你的工作就会变难。 你可能有各种测试不通过或者坏掉。
(前辈的一个简单原则:如果你不能在5分钟弄明白一个测试是做什么的,就删除它)
利用这个机会了解遗产代码是如何运行的,但此时还不能代码让它通过测试 。如果你不能弄明白如何让一个测试通过,注释它,甚至删除它;增加一个注释,当你更全面的了解了测试框架后再回来看它。当前全面的测试不是优先事项。 当前优先事项是为了的工作让基础的测试通过。
如果代码使用的是旧版本的RSpec,更新RSpec。
Test-Driven Exploration
black-box testing:
忽略内部结构,测试顶层的输入系统和返回的输出。集成测试,用户输入和系统输出。
因为集成测试是从外部工作的,可以用它来测试遗产代码。不用涉及全面的应用,而是涉及全部功能。
white-box testing:
使用关于系统内部的知识来精确地测试明确的路径。
角色测试:
首先,选择一个方法来测试。这个方法应该涉及一个你计划做的变化 。
然后,写这个测试,我们知道测试会失败。不用深挖内部。先期待一个不可能的结果。让测试告诉你真实结果是什么。
运行测试,测试报告error因为有缺少的依靠,或者测试报告fail因为代码运行了但spit out a different result。
分析:
大多时候会升起error, 因为这里肯定你不知道的一些对象依赖,一些value是不被期待的,或者你在其他方面打破了遗产代码函数的the delicate balance。
你需要弄明白事物。常常不得不创建更多的对象。
最终搞定errors后,你会进一步的理解程序的内部。
然后就可以进行下一个测试了,大多数是在其他测试案例中尝试现存的方法 .
Prescription
当开始给遗产代码写单元测试时,使用测试来探索代码的行为。尝试在不改变原code的情况下写一个passing test,用测试来反应问题。
Pry对此是有帮助的。一旦在console能明白事情,转化这个命令给测试以便它们能反复运行。
What Tool Should I Use? (Legacy Edition)
之前用什么工具,这里也用这个工具。如果没有使用factory,作者推荐用。设置一个factory工具来创建关联会节省时间。
⚠️提示 :
如果原来的程序员使用的工具不足以支持你想要的测试或者现存的测试你觉得是无用的,那么删除它们,从新开始。此时你可以挑选你想要的任何工具。
Dependency Removal 依赖移除
在遗产测试中,依赖是最大的挑战。可能TDD code最帮的优势就是测试会强迫代码的各个独立片段之间最大化的相互独立。
Keep Things Separate
让你的新代码不要依赖遗产代码最容易的办法是你自己分开它们。如果可能,在新的类或新的方法中写新代码。仅仅调用那些遗产代码。
如果你新增或者提取了大量函数,你需要考虑创建你自己的独立类而不是仅仅增加一个方法。
出于测试目的,移动新代码到一个新的类能让测试新的代码更容易,因为新代码较少依赖现存的程序。
不过这样做,也有短期的不好效果,让代码不好懂(因为逻辑增加了)。 在任何案例,你都在原始的混乱代码和更好的重构和组织版本之间的过渡状态。
Legacy Databases, Testing, and You
column contraint 列的约束。
你有可能遇到混乱的数据结构。如奇怪的命名约定或者不常见的ActiveRecord功能。但是它们不影响你测试功能的能力。
你需要小心的是十分数据库增加了非常不明显的约束代码。如foreign key约束。尤其是老版本rails。
从一个测试透明度来看,这个问题更严重。首先业务逻辑在rails代码之外,在数据库里。这样的逻辑很难发现和测试以及改变。更坏的是,foreignkey约束增加了某些对象件的依赖。在测试环境中,一些对象需要一起创建导致了奇怪的bugs。因此需要留意一个重数据库而不信任activerecord的开发团队的遗产代码。
Using Test Doubles to Remove Dependencies
使用double, mock, stub来启动测试,测试那些没有被测试过的代码。
在遗产代码中,这样的好处是使用test doubles可以从程序中隔离单独的class和方法,把关注点放在你所注意的部分。
比如当前测试会用到一个不是当前需要测试的相关方法,你只需要设定一个正确的返回值就行了。这样就把注意力集中在你需要注意的部分。
如,把credit_card_is_valid?设置成一个stub,方便之后的运行。
allow(order).to receive(:credit_card_is_valid?).at_least(:once).and_return(true)
Find the Seam
A seam是一个你可以改变程序的行为但无需改动代码的地方。通过在代码中找到seam并利用它们来测试遗产函数。
A test double可以称为a seam是因为在测试中增加的double,通过授权对一个方法调用产生一个指定的响应,改变了程序代码的行为,但实际上没有执行这个方法。同时,在测试环境中,这个方法的行为改变现存的开发代码也就不会影响到产品代码。
do one thing at a time, to the extent possible.
当你增加新的功能时,不要扩展测试范围。
当你扩展测试范围时,不要试图把代码弄的太整洁。(有时难以避免)
每一步,做的事情尽可能的少,这样一旦发现错误就容易定位到。
Rails 5 Test Prescriptions 最后一章,如何测试继承下来的代码,legacy code的更多相关文章
- Rails 5 Test Prescriptions 第4章 什么制造了伟大的测试
伴随着程序成长,测试变长,复杂性增加,如何更高效的写测试,对以后开发不会造成麻烦. 测试本身没发被测试,所以一定要清楚,可控.不要加循环,不要过于复杂的自动编程. Cost and Value 成本和 ...
- Rails 5 Test Prescriptions 第11章其他部分的测试。
Routes✅ Helper Methods✅ Controllers and Requests✅ Simulating Requests⚠️,看之前的博客 What to Expect in a R ...
- Rails 5 Test Prescriptions 第9章 Testing-JavaScript: Integration Testing,❌挂一个问题webpacker::helper
使用Capybara进行JS的集成测试 谈论驱动 让测试通过 Webpack in Development Mode Js设计 是用户在网页上有好的体验的重要因素. 尽管如此,许多网页不测试JS. 部 ...
- Rails 5 Test Prescriptions 第8章 Integration Testing with Capybara and Cucumber
Capybara: A complete reference is available atrubydoc.info. 集成测试就是把局部的程序组合起来测试. 端到端测试是一个特殊的集成测试,覆盖了 ...
- Rails 5 Test Prescriptions 第5章 Testing Models
Rails,model层包含业务逻辑和储存逻辑.其中储存逻辑被ActiveRecord处理. 在model中,不是每件事都必须是ActiveRecord对象.model layer可以包含各种服务,对 ...
- Rails 5 Test Prescriptions 第3章Test-Driven Rails
本章,你将扩大你的模型测试,测试整个Rails栈的逻辑(从请求到回复,使用端到端测试). 使用Capybara来帮助写end-to-end 测试. 好的测试风格,包括端到端测试,大量目标明确的单元测试 ...
- Rails 5 Test Prescriptions 第10章 Testing for Security
Web 安全是一个可怕的主题.所有的你的程序都依靠密码学,代码超出了你的控制. 尽管如此,你还是可以控制部分网页安全 --所有的logins和access checks和injection error ...
- Rails 5 Test Prescriptions 第10章 Unit_Testing JavaScript(新工具,learn曲线太陡峭,pass)
对Js的单元测试是一个大的题目.作者认为Ruby的相关测试工具比Js的测试工具更灵活 大多数Js代码最终是关于响应用户的行为和改变DOM中的元素 没有什么javascript的知识点.前两节用了几个新 ...
- Rails 5 Test Prescriptions 第7章 double stub mock
https://relishapp.com/rspec/rspec-mocks/v/3-7/docs/basics/test-doubles 你有一个问题,如果想为程序添加一个信用卡程序用于自己挣钱. ...
随机推荐
- CentOS7使用yum安装nginx
CentOS默认没有nginx的yum源需要yum安装nginx可以使用一下方法 一,环境检测 二,设置yum源 rpm -Uvh http://nginx.org/packages/centos/7 ...
- day12(jsp指令&内置对象&动作标签、JavaBean、EL表达式&函数库)
day12 JSP指令 JSP指令概述 JSP指令的格式:<%@指令名 attr1="" attr2="" %>,一般都会把JSP指令放到JSP文件 ...
- TCP协议通讯工作原理
TCP协议通讯工作原理 一.TCP三次握手 传输控制协议(Transport Control Protocol)是一种面向连接的,可靠的传输层协议.面向连接是指一次正常的TCP传输需要通过在TCP ...
- POJ1523:SPF(无向连通图求割点)
题目:http://poj.org/problem?id=1523 题目解析: 注意题目输入输入,防止PE,题目就是求割点,并问割点将这个连通图分成了几个子图,算是模版题吧. #include < ...
- PAT 1109 Group Photo[仿真][难]
1109 Group Photo(25 分) Formation is very important when taking a group photo. Given the rules of for ...
- STL学习笔记---STL简介
1.概述 STL是通用类模版和算法的集合,它提供给程序员一些标准的数据结构和算法的实现.STL三大关键组成: 容器(Containers),用来管理类对象的集合 迭代器(Iterators),用来在一 ...
- cocos进阶教程(5)回调函数和定时器的使用技巧
cc.CallFunc.create(selector, data) selector:函数名(函数指针) data:参数 table类型 函数写法 function(node,args ) node ...
- Entity Framework 数据生成选项DatabaseGenerated(转)
在EF中,我们建立数据模型的时候,可以给属性配置数据生成选项DatabaseGenerated,它后有三个枚举值:Identity.None和Computed. Identity:自增长 None:不 ...
- .Ignite是什么
Ignite是什么 Apache Ignite内存数据组织是高性能的.集成化的以及分布式的内存平台,他可以实时地在大数据集中执行事务和计算,和传统的基于磁盘或者闪存的技术相比,性能有数量级的提升. ...
- jQuery源码分析--Event模块(2)
接下来就是触发事件了.事件触发后的处理函数的分发主要靠两个函数,一个jQuery.event.dispatch,一个是jQuery.event.handlers.这个dispatch会调用handle ...