我认为小测试意味着您不应该在一次测试中测试很多东西。 例如,在我使用 D 上的这些参数调用 Method1()、Method2() 和 Method3() 后,组件 DA、B 和 C 是否处于状态 1、状态 2 和状态 3 中。 每个测试应该只测试一件事。 您可以搜索 SO 来寻找良好测试的质量。 但我认为您的测试是一个小测试,因为它简短且专注于一项任务 -“从制造订单获取零件编号”
更新:作为尝试建议(来自 Beck 书中的 AFAIR),您可能想坐下来在一张纸上列出 SUT 的单行测试列表。 现在您可以选择最简单的(您有信心能够完成的测试。)以建立一些信心。 或者您可以尝试一种您有 80% 的信心但有一些灰色区域的尝试(也是我的选择),因为它将帮助您一路了解有关 SUT 的一些知识。 保留那些你不知道如何继续进行的内容直到最后......希望当更简单的内容完成时它会更清楚。 当它们变绿时,将它们一一击落。
This is perfectly okay as a starting test. With this you define expected behavior - how it should work. Now if you feel you've taken a much bigger bite than you'd have liked.. you can temporarily ignore this test and write a more granular test that takes out part or atleast mid-way. Then other tests that take you towards the goal of making the first big test pass. Red-Green-Refactor at each step.
Small tests, I think mean that you should not be testing a whole lot of stuff in one test. e.g. Are components D.A, B and C in state1, state2 and state3 after I've called Method1(), Method2() and Method3() with these parameters on D. Each test should test just one thing. You can search SO for qualities of good tests. But I'd consider your test to be a small test because it is short and focussed on one task - 'Getting PartNumbers From Manufacturing Order'
Update: As a To-Try suggestion (AFAIR from Beck's book), you may wanna sit down and come up with a list of one-line tests for the SUT on a piece of paper. Now you can choose the easiest (tests that you're confident that you'll be able to get done.) in order to build some confidence. OR you could attempt one that you're 80% confident but has some gray areas (my choice too) because it'll help you learn something about the SUT along the way. Keep the ones that you've no idea of how to proceed for the end... hopefully it'll be clearer by the time the easier ones are done. Strike them off one by one as and when they turn green.
I think you have a good start but don't quite see it that way. The test that is supposed to spawn more tests makes total sense to me as if you think about it, do you know what a Manufacturing Order number or a Part Number is yet? You have to build those possibly which leads to other tests but eventually you'll get down to the itty bitty tests I believe.
Here's a story that may require a bit of breaking down:
As a User I want to submit a manufacturing order number and receive a list of serializable part numbers of that orders bill of materials
I think the key is to break things down over and over again into tiny pieces that make it is to build the whole thing. That "Divide and conquer" technique is handy at times. ;)
Well well, you've hit the exact same wall I did when I tried TDD for the first time :)
Since then, I gave up on it, simply because it makes refactoring too expensive - and I tend to refactor a lot during the initial stage of development.
With those grumpy words out of the way, I find that one of the most overseen and most important aspects of TDD is that it forces you to define your class-interfaces before actually implementing them. That's a very good thing when you need to assemble all your parts into one big product (well, into sub-products ;) ). What you need to do before writing your first tests, is to have your domain model, deployment model and preferably a good chunk of your class-diagrams ready before coding - simply because you need to identify your invariants, min- and max-values etc., before you can test for them. You should be able to identify these on a unit-testing level from your design.
Soo, in my experience (not in the experience of some author who enjoys mapping real world analogies to OO :P ), TDD should go like this:
Create your deployment diagram, from the requirement specification (ofc, nothing is set in stone - ever)
Pick a user story to implement
Create or modify your domain model to include this story
Create or modify your class-diagram to include this story (including various design classes)
Identify test-vectors.
Create the tests based on the interface you made in step 4
Test the tests(!). This is a very important step..
编写控制器的简单实现以确保返回一些内容: return new List{new MfgOrder(), new MfgOrder(), new MfgOrder()}; 例如,您还需要为 MfgOrder 实现类。
现在您的 UI 可以正常工作了! 工作不正确,但工作正常。 因此,我们期望控制器从服务或 DAO 获取数据。 在测试用例中创建一个 Mock DAO 对象,并添加调用方法“partsDao.GetPartsInMfgOrder()”的期望。
使用该方法创建 DAO 类。 从控制器调用该方法。 您的控制器现已完成。
创建一个单独的测试来测试 DAO,最终确保它从数据库返回正确的数据。
不断迭代,直到全部完成。 过了一会儿,你就会习惯的。
这里的要点是将应用程序分成非常小的部分,并单独测试这些小部分。
Here's how I would start. Lets suppose you have absolutely no code for this application.
Define the user story and the business value that it brings: "As a User I want to submit a manufacturing order number and a list of part numbers of that orders so that I can send the list to the inventory system"
start with the UI. Create a very simple page (lets suppose its a web app) with three fields: label, list and button. That's good enough, isn't it? The user could copy the list and send to the inv system.
Use a pattern to base your desig on, like MVC.
Define a test for your controller method that gets called from the UI. You're testing here that the controller works, not that the data is correct: Assert.AreSame(3, controller.RetrieveParts(mfgOrder).Count)
Write a simple implementation of the controller to make sure that something gets returned: return new List<MfgOrder>{new MfgOrder(), new MfgOrder(), new MfgOrder()}; You'll also need to implement classes for MfgOrder, for example.
Now your UI is working! Working incorrectly, but working. So lets expect the controller to get the data from a service or DAO. Create a Mock DAO object in the test case, and add an expectation that the method "partsDao.GetPartsInMfgOrder()" is called.
Create the DAO class with the method. Call the method from the controller. Your controller is now done.
Create a separate test to test the DAO, finally making sure it returns the proper data from the DB.
Keep iterating until you get it all done. After a little while, you'll get used to it.
The main point here is separating the application in very small parts, and testing those small parts individually.
发布评论
评论(4)
作为起始测试,这是完全可以的。 通过它,您可以定义预期的行为 - 它应该如何工作。 现在,如果您觉得自己咬了一口比您希望的要大得多..您可以暂时忽略此测试并编写一个更细粒度的测试,该测试可以删除部分或至少中途。 然后其他测试将带您实现通过第一个大测试的目标。 每一步都进行红-绿-重构。
我认为小测试意味着您不应该在一次测试中测试很多东西。 例如,在我使用 D 上的这些参数调用 Method1()、Method2() 和 Method3() 后,组件 DA、B 和 C 是否处于状态 1、状态 2 和状态 3 中。
每个测试应该只测试一件事。 您可以搜索 SO 来寻找良好测试的质量。 但我认为您的测试是一个小测试,因为它简短且专注于一项任务 -“从制造订单获取零件编号”
更新:作为尝试建议(来自 Beck 书中的 AFAIR),您可能想坐下来在一张纸上列出 SUT 的单行测试列表。 现在您可以选择最简单的(您有信心能够完成的测试。)以建立一些信心。 或者您可以尝试一种您有 80% 的信心但有一些灰色区域的尝试(也是我的选择),因为它将帮助您一路了解有关 SUT 的一些知识。 保留那些你不知道如何继续进行的内容直到最后......希望当更简单的内容完成时它会更清楚。 当它们变绿时,将它们一一击落。
This is perfectly okay as a starting test. With this you define expected behavior - how it should work. Now if you feel you've taken a much bigger bite than you'd have liked.. you can temporarily ignore this test and write a more granular test that takes out part or atleast mid-way. Then other tests that take you towards the goal of making the first big test pass. Red-Green-Refactor at each step.
Small tests, I think mean that you should not be testing a whole lot of stuff in one test. e.g. Are components D.A, B and C in state1, state2 and state3 after I've called Method1(), Method2() and Method3() with these parameters on D.
Each test should test just one thing. You can search SO for qualities of good tests. But I'd consider your test to be a small test because it is short and focussed on one task - 'Getting PartNumbers From Manufacturing Order'
Update: As a To-Try suggestion (AFAIR from Beck's book), you may wanna sit down and come up with a list of one-line tests for the SUT on a piece of paper. Now you can choose the easiest (tests that you're confident that you'll be able to get done.) in order to build some confidence. OR you could attempt one that you're 80% confident but has some gray areas (my choice too) because it'll help you learn something about the SUT along the way. Keep the ones that you've no idea of how to proceed for the end... hopefully it'll be clearer by the time the easier ones are done. Strike them off one by one as and when they turn green.
我认为你有一个良好的开端,但并不这么认为。 应该产生更多测试的测试对我来说完全有意义,就好像您想一下,您知道制造订单号或零件号是什么吗? 您必须构建那些可能导致其他测试的测试,但最终您将进行我相信的微小测试。
这是一个可能需要进行一些分解的故事:
我认为关键是一遍又一遍地分解事情分解成小块,才能构建出完整的东西。 这种“分而治之”的技巧有时很方便。 ;)
I think you have a good start but don't quite see it that way. The test that is supposed to spawn more tests makes total sense to me as if you think about it, do you know what a Manufacturing Order number or a Part Number is yet? You have to build those possibly which leads to other tests but eventually you'll get down to the itty bitty tests I believe.
Here's a story that may require a bit of breaking down:
I think the key is to break things down over and over again into tiny pieces that make it is to build the whole thing. That "Divide and conquer" technique is handy at times. ;)
好吧,你遇到的情况与我第一次尝试 TDD 时遇到的情况完全相同:)
从那时起,我就放弃了它,仅仅是因为它使重构成本太高 - 而且我倾向于在最初的时候进行大量重构发展阶段。
抛开这些脾气暴躁的话,我发现 TDD 最受监督和最重要的方面之一是它迫使您在实际实现类接口之前定义它们。 当您需要将所有部件组装成一个大产品(嗯,组装成子产品;))时,这是一件非常好的事情。 在编写第一个测试之前,您需要做的是在编码之前准备好域模型、部署模型,最好是准备好大部分类图 - 只是因为您需要识别不变量、最小值和最大值等.,然后才能测试它们。 您应该能够在设计的单元测试级别上识别这些。
Soo,根据我的经验(而不是一些喜欢将现实世界类比映射到 OO 的作者的经验:P),TDD 应该像这样:
Well well, you've hit the exact same wall I did when I tried TDD for the first time :)
Since then, I gave up on it, simply because it makes refactoring too expensive - and I tend to refactor a lot during the initial stage of development.
With those grumpy words out of the way, I find that one of the most overseen and most important aspects of TDD is that it forces you to define your class-interfaces before actually implementing them. That's a very good thing when you need to assemble all your parts into one big product (well, into sub-products ;) ). What you need to do before writing your first tests, is to have your domain model, deployment model and preferably a good chunk of your class-diagrams ready before coding - simply because you need to identify your invariants, min- and max-values etc., before you can test for them. You should be able to identify these on a unit-testing level from your design.
Soo, in my experience (not in the experience of some author who enjoys mapping real world analogies to OO :P ), TDD should go like this:
我将这样开始。 假设您完全没有此应用程序的代码。
Assert.AreSame(3,controller.RetrieveParts(mfgOrder).Count)
return new List{new MfgOrder(), new MfgOrder(), new MfgOrder()};
例如,您还需要为 MfgOrder 实现类。这里的要点是将应用程序分成非常小的部分,并单独测试这些小部分。
Here's how I would start. Lets suppose you have absolutely no code for this application.
Assert.AreSame(3, controller.RetrieveParts(mfgOrder).Count)
return new List<MfgOrder>{new MfgOrder(), new MfgOrder(), new MfgOrder()};
You'll also need to implement classes for MfgOrder, for example.The main point here is separating the application in very small parts, and testing those small parts individually.