我很好地掌握了单元测试,DI,模拟以及所需的所有设计主要优点,以尽可能接近完整的代码覆盖范围(单一责任主体,在我编码时考虑'我将如何测试'等等. ..).
我最近的应用程序,我没有编写真正的TDD代码.在编写代码时我记住了单元测试,并在编写代码,重构等之后编写了我的测试.当它很容易做时我做了TDD ...但是我没有像我现在这样做......这是我第一个充分利用DI,模拟框架等的项目,以及第一个完全代码覆盖的项目 - 随着我的进展,我从中学到了很多东西.我很想分配到我的下一个项目,所以我可以从头开始完全编写TDD代码.
我知道这是一个广泛的问题,我已经通过示例和XP Unleashed订购了TDD,但我希望简要概述一下如何设计/编写一个大型应用程序来进行TDD.
你是否编写了整个应用程序,只使用了存根代码?(例如,编写所有函数签名,接口,结构,并编写整个应用程序但不编写任何实际实现)?我可以想象它适用于中小型,但这在大型应用程序中是否可行?
如果没有,你会如何编写系统中最高级别功能的第一次单元测试?让我们举例说 - 在一个Web服务上,你有一个名为DoSomethingComplicated(param1,...,param6)的函数暴露给世界.显然,首先为AddNumbers()之类的简单函数编写测试是微不足道的 - 但是当函数位于调用堆栈的顶部时,如此?
你还做前期设计吗?显然你仍然想做'架构'设计 - 例如,一个流程图显示IE与IIS交谈,它通过WCF与Windows服务进行通信,该服务与SQL数据库进行通信...显示所有SQL表及其字段的ERD,等......但是课堂设计呢?课程之间的相互作用等?你是在预先设计这个,还是继续编写存根代码,在你进行时重构交互,直到整个事物连接起来并且看起来它会起作用?
任何建议都非常感谢
小智 20
你当然可以.你面前有一个很大的应用程序.在开始编写测试和代码之前,您必须了解它将具有的结构.您不必详细了解所有内容,但您应该对层,组件和接口有一些基本的了解.例如,如果您正在使用Web服务系统,您应该知道顶级服务是什么,并且他们的签名具有良好的第一近似值.
不会.只有在测试中真的很难控制它们时才能把它们存在.例如,我喜欢存根数据库和UI.我还将删除第三方接口.有时,如果它大大增加了测试时间,我会将我自己的一个组件存根,或者它迫使我创建太复杂的测试数据.但大多数时候我让我的测试工作在一个非常好的集成系统上.
我不得不说我真的不喜欢严重依赖于模拟和存根的测试风格.不要误解我的意思,我认为模拟和存根对于解决难以测试的事物非常有用.但我不喜欢编写难以测试的东西,因此我不会使用大量的模拟和存根.
大多数高级函数都具有退化行为.例如,登录是一个非常高级别的功能,可能非常复杂.但是如果您尝试使用没有用户名和密码登录,系统的响应将非常简单.编写测试也很简单.所以你从堕落的案例开始.一旦你筋疲力尽,你就会进入下一个复杂程度.例如,如果用户尝试使用用户名但没有密码登录,该怎么办?一点一点地爬上复杂的阶梯,从不解决更复杂的方面,直到不那么复杂的方面全部通过.
这种策略的运作情况非常出色.你可能会认为你只是一直爬到边缘,从来没有吃过肉; 但事实并非如此.相反,您会发现自己基于所有退化和异常情况设计代码的内部结构.当你最终到达主要流程时,你会发现你正在处理的代码的结构有一个很好的洞,其形状恰好可以插入主流.
用户界面是误导性的东西.它们使您专注于系统的错误方面.相反,假设您的系统必须具有许多不同的UI.有些将是网络,有些将是厚客户端,有些将是纯文本.无论UI如何,都要将系统设计为正常工作.通过所有测试,首先获取所有业务规则.然后在以后插入UI.我知道,面对很多传统智慧,这种情况很快,但我不会以任何其他方式做到这一点.
数据库是细节.保存详细信息以供日后使用 相反,将系统设计为好像不知道您使用的是哪种数据库,将架构,表,行和列的任何概念保留在系统核心之外.实现业务规则,就好像所有数据始终保存在内存中一样.一旦您完成了所有业务规则,就可以在以后添加数据库.同样,我知道面对一些传统智慧,这种情况很快,但过早地将系统耦合到数据库是许多严重扭曲设计的根源.
Mar*_*ann 12
我是否只使用存根代码编写整个应用程序?
不,没有丝毫意义 - 这听起来像是一种非常浪费的方法.我们必须始终牢记,做TDD的根本原因是快速反馈.自动测试套件可以告诉我们是否比手动测试更快地破坏了任何东西.如果我们等到最后一刻连接在一起,我们就不会得到快速反馈 - 虽然我们可能会从单元测试中获得快速反馈,但我们不知道应用程序是否作为一个整体工作.单元测试只是我们为验证应用程序而需要执行的一种测试形式.
更好的方法是从最重要的功能开始,并使用从外到内的方法从那里开始工作.这通常意味着从一些UI开始.
我这样做的方法是创建所需的UI.由于我们通常无法使用TDD开发UI,因此我只需使用所选技术创建View.那里没有测试,但是我将UI连接到一些API(最好使用声明性数据绑定),这就是测试开始时的情况.
在开始时,我会TDD我的ViewModel/Presentation Models和相应的控制器,可能硬编码一些响应,看看UI工作.一旦我运行它时没有爆炸的东西,我会检查代码(记住,许多小的增量签入).
我随后垂直向下工作,并确保这个特定的UI可以一直到数据源(或其他),忽略所有其他功能.
功能完成后,我可以开始下一个功能.我描绘这个过程的方式是我通过一次做一个垂直切片来填写应用程序,直到完成所有功能.
以这种方式开始一个绿地应用程序总是花费很长时间来完成第一个功能,因为这是你必须连接所有内容的地方,所以选择一些简单的东西(比如应用程序的初始视图)来保持尽可能简单.第一个功能完成后,下一个功能变得更加容易,因为基础已经到位.
我还在前面设计吗?
不多,不.在开始之前,我通常会考虑整体设计,当我在团队中工作时,我们会在开始之前在白板或幻灯片上绘制整体架构.
这或多或少受限于
其余的我们一目了然,但随着我们的进展,我们在白板上使用了许多临时设计会话.
| 归档时间: |
|
| 查看次数: |
870 次 |
| 最近记录: |