- 浏览: 198485 次
文章分类
- 全部博客 (185)
- A Design Patterns (2)
- B Refactoring (0)
- C Test (2)
- D Software Engineering (0)
- E Other Tech Articles (4)
- F My Blog (0)
- G TechJie forum & QQ group (2)
- H Programmer (6)
- I 杂7杂8 (4)
- J Translations (0)
- [网站分类]1.首页原创精华.NET区(包含架构设计、设计模式)(对首页文章的要求:原创、高质量、经过认真思考并精心写作) (3)
- [网站分类]2..NET新手区(用于发表不合适发表在首页的.NET技术文章,包括小经验、小技巧) (14)
- [网站分类]3.非技术区(技术之外的文章,但不要涉及任何政治内容) (40)
- [网站分类]4.其他技术区 (9)
- [网站分类]5.企业信息化 (0)
- [网站分类]6.读书心得区(技术书籍阅读心得、书籍推荐) (8)
- [网站分类]7.提问区(.NET技术方面的提问) (6)
- [网站分类]8.技术转载区(.NET技术文章转载, 请注明原文出处) (24)
- [网站分类]9.求职招聘区(个人求职、企业招聘) (0)
- [网站分类]GIS技术 (0)
- [网站分类]SharePoint (0)
- [网站分类]博客园.NET俱乐部(俱乐部组织与活动方面的文章) (2)
- [网站分类]软件发布区(发布自己开发的代码、软件) (0)
- [网站分类]网站管理区(网站管理方面的疑问、建议、意见, 寻求管理员帮助) (0)
- [网站分类]业界新闻 (6)
最新评论
-
没有终点:
不懂 lz说的是啥 我太菜了
超简单SVN教程 -
韩悠悠:
超简单SVN教程 -
DraculaW:
orz...如果让他去写书很好奇这个作者会怎么解释vector ...
又见热书讨论《JavaScript征途》 -
gigix:
weiqingfei 写道为什么国内写书的都是烂人?
为什么高 ...
又见热书讨论《JavaScript征途》 -
weiqingfei:
为什么国内写书的都是烂人?为什么高手都不写书?
又见热书讨论《JavaScript征途》
zz from :http://www.artima.com/weblogs/viewpost.jsp?thread=35578
See another zz blog: One Expectation Per Test
Shift Your Paradigm!
One Assertion Per Test
by Dave Astels
February 23, 2004
Summary
For some time I've been thinking about how TDD tests can be as simple, as expressive, and as elegant as possible. This article explores a bit about what it's like to make tests as simple and decomposed as possible: aiming for a single assertion in each test.
A while ago there was a bit of fuss on the testdrivendevelopment Yahoo group about the idea of limiting yourself to one assertion per test method, which is a guideline that others and I offer for TDD work.
An address parser was the example of a situation where it was argued that multiple assertions per test made sense. Date was formatted with one address per line, each in one of the following formats:
- ADDR1$ADDR2$CSP$COUNTRY
- ADDR1$ADDR2$CSP
- ADDR1$CSP$COUNTRY
- ADDR1$CSP
The poster went on to say: My first inclination is/was to write a test like this:
a = CreateObject("Address") a.GetAddressParts("ADDR1$ADDR2$CITY IL 60563$COUNTRY") AssertEquals("ADDR1", a.Addr1) AssertEquals("ADDR2", a.Addr2) AssertEquals("CITY IL 60563", a.CityStatePostalCd) AssertEquals("Country", a.Country)
They didn't see how to achieve this with one assertion per test, as there are obviously four things to test in this case. I decided that rather than simply reply, I would write some tests and code to illustrate my view on the matter, and offer a solid response.
For this problem, I chose Squeak Smalltalk (see www.squeak.org) and Java. For the sake of conciseness, I'll omit any required accessors.
So, where to start? Well, when doing TDD it often makes sense to start with something simple to quickly and easily get some code written and working. Then it can be extended and evolved in response to further test driving. Here the simplest case is: ADDR1$CSP. There are two requirements in the parsing of this example: that the ADDR1 was recognized, and that the CSP was recognized. Viewed this way, we need two tests. We start with one for ADDR1:
Squeak:
testAddr1 | anAddress | anAddress := Address from: 'ADDR1$CITY IL 60563'. self assert: anAddress addr1 equals: 'ADDR1'
Java:
public void testAddr1() throws Exception { Address anAddress = new Address("ADDR1$CITY IL 60563"); assertEquals("ADDR1", anAddress.getAddr1()); }
To get this to pass we need an Address class and a from: factory method, which creates an instance and has it parse the address string. For brevity, I'll skip the "return literal" step.
Squeak:
Object subclass: #Address instanceVariableNames: 'addr1' classVariableNames: '' poolDictionaries: '' category: 'Adaption-One Assertion Test' (class method) from: aString ^self new parse: aString; yourself parse: aString | parts | parts := aString findTokens: '$'. addr1 := (parts at: 1)
Java:
public class Address { private String addr1; public Address(String aString) { parse(aString); } private void parse(String aString) { StringTokenizer parts = new StringTokenizer(aString, "$"); addr1 = parts.nextToken(); } }
That's well & good. The next test is for CSP.
Squeak:
testCsp | anAddress | anAddress := Address from: 'ADDR1$CITY IL 60563'. self assert: anAddress csp equals: 'CITY IL 60563'
Java:
public void testCsp() throws Exception { Address anAddress = new Address("ADDR1$CITY IL 60563"); assertEquals("CITY IL 60563", anAddress.getCsp()); }
Address>>parse: will need to be extended (and we need to add a csp instance variable and accessors):
Squeak:
parse: aString | parts | parts := aString findTokens: '$'. addr1 := (parts at: 1). csp := (parts at: 2)
Java:
private void parse(String aString) { StringTokenizer parts = new StringTokenizer(aString, "$"); addr1 = parts.nextToken(); csp = parts.nextToken(); }
So. We have two tests for this one situation. Notice the duplication in the tests... the creation of the instance of Address that is being probed. This is the fixture. After refactoring, we have:
Squeak:
TestCase subclass: #Addr1CspTests instanceVariableNames: 'anAddress ' classVariableNames: '' poolDictionaries: '' category: 'Adaption-One Assertion Test'! setUp anAddress := Address from: 'ADDR1$CITY IL 60563' testAddr1 self assert: anAddress addr1 equals: 'ADDR1' testCsp self assert: anAddress csp equals: 'CITY IL 60563'
Java:
public class Addr1CspTests extends TestCase { private Address anAddress; protected void setUp() throws Exception { anAddress = new Address("ADDR1$CITY IL 60563"); } public void testAddr1() throws Exception { assertEquals("ADDR1", anAddress.getAddr1()); } public void testCsp() throws Exception { assertEquals("CITY IL 60563", anAddress.getCsp()); } }
So, a fixture that creates the Address instance from the string, and very simple tests that focus on each aspect of that fixture.
The next simplest case is the obvious choice for the next fixture:
Squeak:
setUp anAddress := Address from: 'ADDR1$CITY IL 60563$COUNTRY'
Java:
protected void setUp() throws Exception { anAddress = new Address("ADDR1$CITY IL 60563$COUNTRY"); }
This set of tests will include ones for addr1 and csp as before (refactoring this to remove that duplication is left to the reader) as well as a new test for country:
Squeak:
testCountry self assert: anAddress country equals: 'COUNTRY'
Java:
public void testCountry() throws Exception { assertEquals("COUNTRY", anAddress.getCountry()); }
As before, an instance variable and associated accessors need to be added to the Address class.
This drives Address>>parse: to evolve:
Squeak:
parse: aString | parts | parts := aString findTokens: '$'. addr1 := (parts at: 1). csp := (parts at: 2). country := (parts at: 3 ifAbsent: [''])
Java:
private void parse(String aString) { StringTokenizer parts = new StringTokenizer(aString, "$"); addr1 = parts.nextToken(); csp = parts.nextToken(); country = parts.hasMoreTokens() ? parts.nextToken() : ""; }
From here on, the evolution gets a bit more complex, as we add the ADDR2 option to the mix.
Conclusion
So we took a situation that was thought to require multiple assertions in a test and did it in such as way as to have only one assertion per test.
The key is that instead of using a single TestCase subclass with a complex (i.e. multiple assertion) tests for each situation, we made each of those situations into a separate fixture. Each fixture is implemented by a separate subclass of TestCase. Now each test focuses on a very small, specific aspect of that particular fixture.
I'm convinced writing tests like this is a useful approach. One advantage is that the resulting tests simpler and easier to understand. Just as important, and maybe more so, is that by adding the specification of the behavior one tiny piece at a time, you drive toward evolving the code in small, controllable, understandable steps.
It also fits better into the test fixture centered approach that is the recommended way to organize your tests. We set up the object to test in the setUp method, and tested each aspect of it in individual tests methods.
As I've been writing this, something clicked. I see these test methods as specifications of tiny facets of the required behavior. Thus, it makes sense to me to be as gradual as possible about it, driving the evolution of the code in the smallest steps possible. Striving for one assertion per test is a way to do that.
If, however, you view test methods as strictly performing verification, then I can see how it might be seen to make sense to invoke some code and then test all the postconditions. But this view is not TDD, and doesn't buy you all of the benefits of TDD. I contend that central to TDD is this notion of working in the smallest steps possible, both for the finest-grained long-term verification, and for the most flexible design evolution. Furthermore, this is best done by striving to keep tests as small, focused and simple as possible. Aiming for one assertion per test is one way to get there.
发表评论
-
Rhino Mocks To The Rescure
2006-11-23 09:17 790http://developernotes.com/archi ... -
Some high level concepts
2006-11-23 09:25 953http://structuremap.sourceforge ... -
Singletons Are Evil
2006-11-23 09:56 822http://c2.com/cgi/wiki?Singleto ... -
Best and Worst Practices for Mock Objects
2006-11-23 10:00 768http://codebetter.com/blogs/jer ... -
小函数:让你的函数变短的九个好处
2006-12-04 22:15 1129Small Methods: Nine Benefits ... -
UML序列图(zz)
2007-03-19 11:28 1281级别: 初级 Donald BellIBM 2005 年 2 ... -
重写方法不被认为是在类上声明的
2007-03-22 14:54 557当在类中指定方法时,如果有多个方法与调用兼容(例如,存在两 ... -
One Expectation Per Test(zz)
2007-05-18 10:18 810zz From: http://jupitermoonbeam ... -
Supervising Controller - Martin's "GUI Architectures" series (2)
2007-05-31 12:16 842zz from www.martinfowler.com To ... -
Presentation Model - Martin's "GUI Architectures" series (3)
2007-05-31 12:18 885zz from www.martinfowler.com To ... -
Passive View - Martin's "GUI Architectures" series (4)
2007-05-31 12:19 816zz from www.martinfowler.com To ... -
Rhino Mocks To The Rescure
2006-11-23 09:17 910http://developernotes.com/archi ... -
Some high level concepts
2006-11-23 09:25 882http://structuremap.sourceforge ... -
Singletons Are Evil
2006-11-23 09:56 699http://c2.com/cgi/wiki?Singleto ... -
Best and Worst Practices for Mock Objects
2006-11-23 10:00 600http://codebetter.com/blogs/jer ... -
小函数:让你的函数变短的九个好处
2006-12-04 22:15 807Small Methods: Nine Benefits ... -
UML序列图(zz)
2007-03-19 11:28 1628级别: 初级 Donald BellIBM 2005 年 2 ... -
重写方法不被认为是在类上声明的
2007-03-22 14:54 789当在类中指定方法时,如果有多个方法与调用兼容(例如,存在两 ... -
One Assertion Per Test(zz)
2007-05-18 10:15 793zz from :http://www.artima.co ... -
One Expectation Per Test(zz)
2007-05-18 10:18 1215zz From: http://jupitermoonbeam ...
相关推荐
one of the greatest challenges for today's ASIC and SoC design teams. Rooted in that challenge is the goal to shorten the verification cycle. This requires new design and verification techniques. In ...
assertion-1.8.7.jar
在IT领域,尤其是在软件开发过程中,“Debug Assertion Failed!”是一个常见的错误提示,它通常出现在调试阶段,当程序执行到某一点时,预设的断言条件没有得到满足,从而触发了断言失败。这一现象背后涉及的知识点...
print("Assertion failed:", e) finally: driver.quit() ``` 这段代码首先启动Firefox浏览器,然后等待指定ID的元素出现,并使用`assert`语句检查该元素是否可见。如果元素未找到或不可见,断言就会失败并打印...
### System Verilog Assertion (SVA) 简介 #### 一、SVA 在验证环境中的角色 在现代数字设计的验证过程中,测试平台扮演着关键的角色,它负责完成三大核心任务: 1. **产生激励**:即创建一系列输入信号以驱动...
1. **Assertion宏**:Googletest 提供了一系列的断言宏,如 `EXPECT_EQ`, `ASSERT_TRUE` 等,它们用于在测试中检查预期条件。这些宏在测试失败时会生成有用的错误信息,帮助开发者快速定位问题。 2. **Test Fixture...
这是一本关于 assertion 的资料,目录如下: chapter 2 ASSERTION METHODOLOGY chapter 3 SPECIFYING RTL PROPERTIES chapter 4 PLI-BASED ASSERTIONS chapter 5 FUNCTIONAL COVERAGE chapter 6 ASSERTION PATTERNS ...
### System Verilog Assertion (SVA) 简介 #### 一、SVA定义与优点 **SVA**,即System Verilog Assertions,是System Verilog语言中的一种特性,主要用于形式化验证。它允许设计者定义一系列规则或条件,以确保...
system verilog assertion 应用指南 书中源代码 从学校图书管节的CD拷贝下来的 a practical guide for systemverilog assertions 清华大学出版社 美 Srikanth Vijayaraghavan 等编著 陈俊杰等译
验证与设计不同,尤其是初学者,验证会成为一盘散沙——无规可循。然而 为了能够实现验证平台的重用,需要标准的验证语言和标准的验证库。这样一来 在验证的过程中只需要调用验证库中的库单元就可以实现验证的重用。...
3. **断言(Assertion)**:断言是GoogleTest的核心,用于检查程序的状态是否符合预期。例如,`ASSERT_TRUE` 和 `EXPECT_EQ` 分别用于判断条件是否为真和预期值与实际值是否相等。 4. **主测试程序(Main)**:每个...
4. **断言(Assertion)**:GoogleTest 提供了多种断言,如 `EXPECT_EQ`、`ASSERT_TRUE` 等,用于验证代码执行的结果是否符合预期。 5. **固定测试(Fixtures)**:为了减少重复代码,GoogleTest 支持使用 fixtures...
5. **断言(Assertion)**:断言是一种强大的工具,用于在Testbench 中检查设计的正确性。它们可以在指定条件下强制执行某些条件,如果这些条件不满足,设计就会被标记为错误。 6. **任务和函数**:在Testbench 中...
SystemVerilog Assertion语法总结及应用图例 SystemVerilog Assertions (SVA) 是一種驗證技術,用于确保设计的正确性和可靠性。它為一種指令,指导驗證工具使用形式方法来证明或假設某個属性。Assertions capture ...
3. **断言**:在testbench中使用断言(assertion)可以增强设计的健壮性。它们是条件语句,如果条件不满足,则表明设计可能有错误。这有助于早期发现潜在问题。 4. **随机化**:为了提高测试覆盖率,可以使用...
SystemVerilog断言手册 SystemVerilog Assertions Handbook 是一本专注于SystemVerilog断言的书籍,主要涉及用于形式验证和动态验证的技术。这本书由VhdlCohen Publishing出版,作者对SystemVerilog断言在设计验证...
- **基于断言的验证(Assertion-Based Verification)**: 使用VHDL断言库(e.g., `assert`语句)来指定设计应满足的条件。 - **覆盖率分析(Coverage Analysis)**: 监控测试覆盖指标,如语句覆盖、条件覆盖、路径...
解决Delphi2007在64位系统下Run后每次出现错误 Assertion failure 的DLL替换解决方案! 使用方法: 替换 C:\Program Files (x86)\CodeGear\RAD Studio\5.0\bin 下的同名文件即可!
3. 断言(Assertion):gtest提供了多种断言,如`ASSERT_TRUE`、`EXPECT_EQ`等,用于检查程序的状态是否符合预期。如果断言失败,gtest会打印错误信息并终止当前测试用例。 三、gtest的高级特性 1. 参数化测试:...
- 断言(assertion):断言操作符是SVA的核心,如$rose、$fell用于检测信号的上升沿和下降沿。 - 覆盖(coverage):coverproperty用于统计设计属性的覆盖情况。 ### 断言在实际设计中的应用 在设计验证过程中,SVA...