我们从哪里开始使用单元测试?
我对从哪里开始使用单元测试有些疑问。
我正在 RAD 中使用 Junit 进行单元测试。 我是在所有代码准备好部署之后或者可能在部署之后才执行此操作。 我很困惑为什么我们在代码几乎准备好部署之后还要进行单元测试。
我的问题是我们什么时候应该开始单元测试?
我还有一些问题......
我在单元测试中所做的是从类中获取一个方法并为该方法创建一个测试类。
在该类中,我向该方法提供了一些输入值,并期望来自数据库的受尊重的输出值。
现在,这里单个测试类确实获取输入值 - >将其传递给方法 - >从原始类调用方法 - >数据库连接 - >从数据库获取值 - >将其返回到测试类。
如果测试成功运行,则 Junit 控制台显示绿色条,否则显示红色条。
红色条表示错误原因。但它不会生成任何单元测试报告。
现在这是我的问题...
我是否进行了正确的单元测试? 由于单个单元测试方法包含所有代码流并给出结果......
Where do we start using Unit testing?
I have some doubts about where to start using Unit testing.
I am doing unit testing with Junit in RAD. And I am doing it after all code is ready to deploy or may be after deployment. I am confused why we are doing unit testing after code is almost ready to deploy.
My question is when we should start unit testing?
I have some more questions.....
What I am doing in my unit testing is I took one method from a class and create a test class for that method.
In that class I give some input values to the method and expect respected output values from the database.
Now here the single test class does taking input values->passing it to method->calling the method from original class->database connection->fetching value from DB->return it to test class.
If test successfully runs then Junit console shows Green Bar else Red bar.
Red bar with the cause of error.But it doesn't generate any unit test report.
Now here is my question...
Am I doing correct unit testing? Since a single unit test method comprises all code flow and gives result...
发布评论
评论(7)
如果您还没有开始单元测试,那么现在就是开始单元测试的最佳时机。 单元测试最有效的用途是测试驱动开发 (TDD),其中您在实现每个方法时为其编写测试(编写失败的测试,然后实现该方法以使其通过)。 不过,稍后添加测试还为时不晚。 JUnit 测试巩固了有关代码的某些假设,这些假设稍后可能会发生变化。 如果假设发生变化,测试就会失败,您可能会避免出现一些很难检测到的错误。
我不知道报告工具,但您可以添加一个 JUnit ANT 任务,它将测试结果输出到您的构建控制台(或日志,如果捕获了 ant 输出)。
您的数据库测试听起来像是小型集成测试而不是单元测试。 这很好,但如果测试太慢,您可能需要考虑使用模拟对象(通过 JMock 或 EasyMock 等框架)来用假连接替换真实的数据库连接。 这将方法的逻辑与数据库的状态和行为隔离开来,让您可以运行测试而不必担心数据库是否正在运行并存储有测试数据。
有用的链接:
http://en.wikipedia.org/wiki/Test-driven_development
http://www.jmock.org/
http://easymock.org/
http://ideoplex.com/id/25/ant-and-junit
http://ant.apache.org/manual/Tasks/junit.html
http://misko.hevery.com/code-reviewers-guide/(编写可单元测试代码的指南)
[编辑 - 回应评论]:
关于您所做的是否是正确的单元测试,从技术上讲,答案是“否”。 正如我所说,它更像是一个集成测试,这很好,但它做得太多并且有太多依赖项,无法被视为真正的单元测试。 理想情况下,单元测试将测试方法中的逻辑而不是依赖项。 上面提到的编写可测试代码的指南(以及 Misko Hevery 的相关博客)提供了一些关于如何使用接缝编写代码以插入依赖项模拟的好建议。 Michael Feathers 在他的优秀著作有效地使用遗留代码。
关键因素是依赖项注入:可测试方法不会寻找它们的依赖项 - 它们在构造函数中或作为参数接收它们。 如果这需要太多重构,您可以尝试一些技巧,例如将查找依赖项的代码移动到您可以覆盖的受保护或包可见的方法中。 然后,您在子类上运行测试,该子类从这些方法返回模拟对象。
The best time to start unit testing, if you haven't already, is now. The most effective use of unit tests is Test-Driven Development (TDD), in which you write the tests for each method as you implement it (write a test that fails and then implement the method to make it pass). However, it's not too late to add tests later on. JUnit tests solidify certain assumptions about the code that could change later on. If the assumption changes, the test breaks and you might save yourself from some bugs that would have beeen really hard to detect.
I don't know of a report facility, but you can add a JUnit ANT task which will output the test results to your build console (or log, if ant output is captured).
Your database tests sound like small integration tests rather than unit tests. That's good, but if the tests are too slow you might want to consider using mock objects (via a framework like JMock or EasyMock) to replace real DB connections with fake ones. This isolates the logic of the method from the state and behavior of the database and lets you run tests without worrying about whether the DB is running and stocked with test data.
Useful links :
http://en.wikipedia.org/wiki/Test-driven_development
http://www.jmock.org/
http://easymock.org/
http://ideoplex.com/id/25/ant-and-junit
http://ant.apache.org/manual/Tasks/junit.html
http://misko.hevery.com/code-reviewers-guide/ (Guide to writing unit-testable code)
[Edit - in response to comment]:
About whether what you've done is correct unit testing, technically the answer is 'no'. As I said, it's more of an integration test, which is good, but it does too much and has too many dependencies to be considered a real unit test. Ideally, a unit test will test the logic in a method and not the dependencies. The guide to writing testable code mentioned above (as well as the associated blog of Misko Hevery) gives some good advice about how to write code with seams to insert mocks of dependencies. Michael Feathers goes into depth on the subject in his excellent book Working Effectively with Legacy Code.
The key factor is dependency injection: Testable methods don't look for their dependencies - they receive them in the constructor or as arguments. If this requires too much refactoring, there are some tricks you can try, such as moving the code that looks for dependencies into protected or package-visible methods you can override. So then you run the tests on a subclass which returns mock objects from those methods.
您确实应该尽早编写测试,最好是在编写实现之前编写。
我发现这本书在这个主题上很有用,可能值得一读……
http://www.amazon.com/Test-Driven-Development-Addison-Wesley- Signature/dp/0321146530
为了尝试解决您的第二点,您所描述的是“集成测试”,即它不仅测试您的代码单元,还测试您的数据库连接、配置、数据等。
单元测试应该只测试您关心的代码的特定“部分”。 即调用您的方法应该只测试该方法。 它不应该关心数据库连接和数据访问。 您可以使用“模拟”对象来临时替代依赖项来实现此目的。
请参阅:http://msdn.microsoft.com/en-us/library/ aa730844.aspx
虽然此文档来自 Microsoft 并且您使用的是 java,但同样的原则也适用。
希望这可以帮助。
You should really write your tests as early as possible, ideally before you write your implementation.
This is a book that I've found useful on the subject and may be worth a read...
http://www.amazon.com/Test-Driven-Development-Addison-Wesley-Signature/dp/0321146530
To try and address your second point, what you are describing is an "integration test" i.e it is not just testing your unit of code, but also your databases connectivity, configuration, data and the like.
Unit tests should only test the specific "part" of code that you are concerned with. i.e. Calling your method should just test that method. It should not be concerned with Database conectivity and data access. You can achieve this using "Mock" objects to act as a temporary replacement for your dependencies.
See: http://msdn.microsoft.com/en-us/library/aa730844.aspx
Whilst this document is from Microsoft and you're using java, the same principles apply.
Hope this helps.
您应该尽早开发单元测试。 事实上,最好的解决方案是在实现要测试的类之前就开发它们。 然后,每次向您的类添加重要功能时,您都可以运行它们。
单元测试,顾名思义,用于测试操作的“单元”。 您不应该让单个测试执行太多。 此外,单元测试应该测试单个类的功能。
您在这里描述的似乎更像是系统测试。 这是一件好事,但它与单元测试完全不同。
You should develop your unit tests as early as possible. In fact the best solution would be to develop them even before you implement the classes to test. Then you run them every time significant functionality is added to your classes.
Unit tests, as their name implies, are used to test a "unit" of operation. You shouldn't have a single test performing too much. Also a unit test should be testing functionality from a single class.
What you describe here seems more like system testing. This is something good to have, but it is a complete different thing than unit testing.
进行认证开发需要您遵循定义的开发模型。 最常用的模型是 V 模型,简单地说,它定义了需求、规格、子规格(例如组件、模块或单元的规格)等。从上到下,在 V 的左分支上。您最终到达了底部V 当规范定义的原子单元无法合理地分解为更小的部分时。
在 V 模型的右侧分支上,您可以验证开发的模块是否符合其规格和/或要求。 通常用于并行或在实施 UUT(被测单元)之前创建测试。
通过这种方式,您可以确保任何模块从一开始甚至在进行一些返工时都适合其框架。
正如其他人所说,尽可能使用模拟等使测试尽可能简单。 您还应该自动化您的测试,至少是那些与靠近 V 底部的模块相关的测试,因为这些测试通常比靠近顶部的测试运行得更频繁。
当您的测试具有明确定义的输出时,制作正确的报告会容易得多。 我们通常有一个枚举(通过、失败、错误)、状态号和消息文本的结构。
Doing certified development requires you to follow a defined devellopment model. The mostly used model is the V model, that, simply said, defines requirements, specs, subspecs (e.g. specs for components, modules or units) etc. top down on the left branch of the V. You than finally reach the bottom of the V when the specs define an atomic unit that can not reasonably be broken into smaller parts.
On the right branch of the V model you perform validations that the develloped module complies with its specs and/or reqs. It is typical use to create a test in parallel or before implementing the UUT (unit under test).
This way you asure that any module fits into its framework from begin on and even when doing some rework.
As others have said, keep the tests as simple as possible using mocks etc whenever possible. You should also automate your tests, at least those that relate to modules residing near the bottom of the V, as those tests usually are run much more often than those near the top.
Doing proper reports is much easier when your tests have a well defined output. We usually have a struct of an enum (passed, failed, error) a status number and a message text.
在我看来,测试应该从你写完第一个方法的那一刻起就开始了。
在编写方法时对其进行测试对很多事情都有帮助。 其一,当出现问题时,唯一的线索是它在某个特定的类中,如果该类有无数的方法和属性,则很难找出问题所在。 如果您遇到语法错误,显然不会,但是当您将一百万个方法投入其中时,语义错误就会变得非常棘手。
确保每个单独的方法都有效,这是最精细的保证级别,这说明了整个类的稳定性。 如果您对特定方法应该做什么有具体的定义,单元测试不仅可以防止边缘情况语义错误,而且还可以帮助您事先规划程序流程,这可以帮助您避免大规模重构,或更糟糕的情况,重写。
为了进行有效的测试,请确保将类分解为尽可能多的方法。 我知道有些人可能不同意这一点,但是在远离函数其余部分的上下文中执行操作的逻辑的重要部分应该移到它们自己的函数中,以便可以独立测试。 我不会在你的单元测试中执行 SQL 查询。 相反,使用模拟对象来模拟数据库。 测试数据库不是单元测试。
这不仅可以帮助您确保应用程序的完整性,而且还可以在将来需要重构类的某些部分时为您提供帮助。 在 100 行函数中寻找 3 行逻辑是没有意义的。 如果逻辑的这些部分在它们自己的方法中,您可以放心,您的方法不会由于该逻辑而失败。 如果某个函数的怪物发生了故障,那么您就很难知道该函数的哪一部分实际上导致了错误。
我知道这一切可能听起来多余,但我的观点是尽早测试,并且测试经常不仅有助于程序的稳定性,而且可以帮助您编写干净的代码并避免寻找小错误的麻烦。
In my opinion, testing should be done from the moment you finish writing your first method.
Testing methods as you write them helps with a lot of things. For one, when something goes wrong and your only clue is that it's in a particular class, if that class has countless methods and properties, it's hard to figure out what went wrong. Obviously not if you're having a syntax error, but semantic errors become very tricky when you're throwing a million methods into the fray.
Ensuring that each individual method works, which is the most granular level of assurance, speaks volumes of the stability of the complete class. If you have a concrete definition of what a particular method should do, Unit testing not only prevents edge-case semantic errors, but it also helps you plan out the flow of your program before hand, which can help you avoid massive refactoring, or worse, rewriting.
For effective testing, make sure you're breaking your class up into as many methods as possible. I know some might disagree with this, but significant portions of logic that perform actions in a context far removed from the rest of the function should be moved into their own function so it can be tested independently. I wouldn't perform SQL queries in your unit test. Instead, use mock objects to mimic the database. Testing the database isn't unit testing.
Not only will this help you with ensuring the integrity of your application, but it will also help you in the future when parts of the class need to be refactored. There's no sense in hunting down three lines of logic in a 100 line function. If those portions of logic are in their own method, you can rest assured that your method isn't failing due to that logic. If that monster of a function were failing, you would have fewer clues as to which part of the function is actually causing the error.
I know this all might sound redundant, but my point is testing early and testing often not only helps the stability of your program, but it helps you write clean code and avoid the headache of hunting down small errors.
不是“在所有代码都准备好部署之后”。 不是“部署后”。 那就太晚了。 正如许多其他人建议的那样,最好的时间是在编写 TDD 风格的代码之前。
您没有进行“正确”的单元测试。 您正在测试的单元是类方法,但它也在测试数据库连接,这通常会使测试太慢而无法像我们希望的那样频繁运行,而且很脆弱。 这并不是说你的测试没有用——它们很可能有用——它们只是不是好的单元测试。
假设您的数据库中有正确的数据,并且您的程序与其有牢固的连接。 在测试过程中,您的方法将从数据库中获得什么值? 只需直接将该值放入即可测试此方法的功能。 因此即使没有数据库它也可以运行。 那是什么? 你的方法不行吗? 也许是做得太多了。 也许是(a)从数据库获取数据并(b)进行计算。 也许您真的只想测试 (b)(我想您确实想测试)。 因此,将 (a) 和 (b) 分开,给自己一个接缝(按照 Michael Feathers 的术语),您可以在其中注入来自测试方法的测试数据。 你现在有什么? 更好的设计。 每个方法只做一件事情。 更松散的耦合。 你到达那里是因为你的测试引导你到达那里。 这就是测试驱动开发。
Not "after all code is ready to deploy". Not "after deployment". That's too late. As many others have advised, the best time is (just) before code is written, TDD-style.
You're not doing "correct" unit testing. The unit you're testing is the class method, but it's also testing the database connection, which generally makes tests too slow to run as frequently as we'd like, and brittle. That's not to say that your tests are useless - they may well be useful - they're just not good unit tests.
Assume your database had the right data in it and your program had a solid connection to it. What value would your method be getting from the database in the course of your test? Just put that value directly in, to test the functionality of this method. So it runs even without the database. What's that? Your method doesn't work that way? Maybe it's doing too much. Maybe it's (a) getting data from the database and (b) making a calculation. Maybe you really want to test just (b) (I think you do). So split (a) and (b) apart, to give yourself a seam (per Michael Feathers' terminology) at which you can inject the test data from a test method. What do you have now? Better design. Each method doing just one thing. Looser coupling. And you got there because your tests led you there. That is test-driven development.
每次进行更改或编写新代码时,都应该对每个输入组合进行测试。 编写代码永远不会结束,有人有时必须回来进行修复或增强,您的测试将帮助他们知道他们所做的更改没有破坏任何东西。
Everytime you make a change or write new code you should include tests for each and every combination of inputs. Writing code never ends, someone, sometime will have to come back and make a fix or enhancement and your tests will help them know that changes they make havent broken anything.