문제

좋습니다. TDD 시작하기 ..하지만 일반적인 양보가 그냥 수행 하는 것임을 알고 있습니다.하지만 다음과 같은 문제가있는 것 같습니다. 게임 시작 :

  • 컬렉션으로 작업 할 때, 우리가 그것이 작동 할 것이라는 것을 "알고있는"Generics 등을 기반으로하더라도 여전히 명백한 추가 / 제거 / 삽입이 성공적으로 테스트됩니까?
  • 일부 테스트는 구현하는 데 시간이 오래 걸리는 것 같습니다 .. 문자열 출력으로 작업 할 때 이런 종류의 작업을 수행하는 "더 나은"방법이 있습니까? (예 : 파싱하기 전에 객체 모델을 테스트하고, 파싱을 소규모 작업으로 나누고 거기에서 테스트합니다.) 내 마음 속에서 항상 "최종 결과"를 테스트해야하지만 설정에 지루할 수 있고 매우 다양 할 수 있습니다.
  • 사용할 테스트 프레임 워크가 없으므로 (작업은 비용을 지불하지 않음) 더 "연습"할 수 있습니다. 상업적으로 사용할 수있는 좋은 제품이 있습니까? (현재 나는 좋은 'ol Debug.Assert 를 사용하고 있습니다 :)
  • 아마 가장 큰 문제 일 것입니다 .. 때로는 어떤 일이 일어나지 않을 지 모르겠습니다 .. 제 말은, 당신은 승인을 받았지만 저는 항상 제가 시험을 놓칠 수 있다는 것을 염려합니다. . 더 깊이 파고 들어 코드를 깨뜨 리거나 코드를 그대로두고 나중에 모두 무너질 때까지 기다리십니까 (비용이 더 많이 듭니다) ..

    기본적으로 내가 여기서 찾는 것은 " 그냥해라 "가 아니라 " 내가이 일을했고 문제가 있었고 이것으로 해결했습니다 "입니다. .. 개인 경험 :)

도움이 되었습니까?

해결책

First, it is alright and normal to feel frustrated when you first start trying to use TDD in your coding style. Just don't get discouraged and quit, you will need to give it some time. It is a major paradigm shift in how we think about solving a problem in code. I like to think of it like when we switched from procedural to object oriented programming.

Secondly, I feel that test driven development is first and foremost a design activity that is used to flesh out the design of a component by creating a test that first describes the API it is going to expose and how you are going to consume it's functionality. The test will help shape and mold the System Under Test until you have been able to encapsulate enough functionality to satisfy whatever tasks you happen to be working on.

Taking the above paragraph in mind, let's look at your questions:

  1. If I am using a collection in my system under test, then I will setup an expectation to make sure that the code was called to insert the item and then assert the count of the collection. I don't necessarily test the Add method on my internal list. I just make sure it was called when the method that adds the item is called. I do this by adding a mocking framework into the mix, with my testing framework.
  2. Testing strings as output can be tedious. You cannot account for every outcome. You can only test what you expect based on the functionality of the system under test. You should always break your tests down to the smallest element that it is testing. Which means you will have a lot of tests, but tests that are small and fast and only test what they should, nothing else.
  3. There are a lot of open source testing frameworks to choose from. I am not going to argue which is best. Just find one you like and start using it.
  4. All you can do is setup your tests to account for what you want to happen. If a scenario comes up that introduces a bug in your functionality, at least you have a test around the functionality to add that scenario into the test and then change your functionality until the test passes. One way to find where we may have missed a test is to use code coverage.

I introduced you to the mocking term in the answer for question one. When you introduce mocking into your arsenal for TDD, it dramatically makes testing easier to abstract away the parts that are not part of the system under test. Here are some resources on the mocking frameworks out there are:

One way to help in using TDD, besides reading about the process, is to watch people do it. I recommend in watching the screen casts by JP Boodhoo on DNRTV. Check these out:

OK, these will help you see how the terms I introduced are used. It will also introduce another tool called Resharper and how it can facilitate the TDD process. I couldn't recommend this tool enough when doing TDD. Seems like you are learning the process and you are just finding some of the problems that have already been solved with using other tools.

I think I would be doing an injustice to the community, if I didn't update this by adding Kent Beck's new series on Test Driven Development on Pragmatic Programmer.

다른 팁

From my own experience:

  1. Only test your own code, not the underlying framework's code. So if you're using a generic list then there's no need to test Add, Remove etc.

  2. There is no 2. Look over there! Monkeys!!!

  3. NUnit is the way to go.

  4. You definitely can't test every outcome. I test for what I expect to happen, and then test a few edge cases where I expect to get exceptions or invalid responses. If a bug comes up down the track because of something you forgot to test, the first thing you should do (before trying to fix the bug) is write a test to prove that the bug exists.

My take on this is following:

  • +1 for not testing framework code, but you may still need to test classes derived from framework classes.
  • If some class/method is cumbersome to test it may be strong indication that something is wrong with desing. I try to follow "1 class - 1 responsibility, 1 method - 1 action" principle. That way you will be able to test complex methods much easier by doing that in smaller portions.
  • +1 for xUnit. For Java you may also consider TestNG.
  • TDD is not single event it is a process. So do not try to envision everything from the beginning, but make sure that every bug found in code is actually covered by test once discovered.

I think the most important thing with (and actually one of the great outcomes of, in a somewhat recursive manner) TDD is successful management of dependencies. You have to make sure that modules are tested in isolation with no elaborate setup needed. For example, if you're testing a component that eventually sends an email, make the email sender a dependency so that you can mock it in your tests. This leads to a second point - mocks are your friends. Get familiarized with mocking frameworks and the style of tests they promote (behavioral, as opposed to the classic state based), and the design choices they encourage (The "Tell, don't ask" principle).

I found that the principles illustrated in the Three Index Cards to Easily Remember the Essence of TDD is a good guide.

Anyway, to answer your questions

  1. You don't have to test something you "know" is going to work, unless you wrote it. You didn't write generics, Microsoft did ;)
  2. If you need to do so much for your test, maybe your object/method is doing too much as well.
  3. Download TestDriven.NET to immediately start unit testing on your Visual Studio, (except if it's an Express edition)
  4. Just test the correct thing that will happen. You don't need to test everything that can go wrong: you have to wait for your tests to fail for that.

Seriously, just do it, dude. :)

I am no expert at TDD, by any means, but here is my view:

  • If it is completely trivial (getters/setters etc) do not test it, unless you don't have confidence in the code for some reason.
  • If it is a quite simple, but non-trivial method, test it. The test is probably easy to write anyway.
  • When it comes to what to expect not to happen, I would say that if a certain potential problem is the responsibility of the class you are testing, you need to test that it handles it correctly. If it is not the current class' responsibility, don't test it.

The xUnit testing frameworks are often free to use, so if you are a .Net guy, check out NUnit, and if Java is your thing check out JUnit.

The above advice is good, and if you want a list of free frameworks you have to look no farther than the xUnit Frameworks List on Wikipedia. Hope this helps :)

In my opinion (your mileage may vary):

1- If you didn't write it don't test it. If you wrote it and you don't have a test for it it doesn't exist.

3- As everyone's said, xUnit's free and great.

2 & 4- Deciding exactly what to test is one of those things you can debate about with yourself forever. I try to draw this line using the principles of design by contract. Check out 'Object Oriented Software Construction" or "The Pragmatic Programmer" for details on it.

Keep tests short, "atomic". Test the smallest assumption in each test. Make each TestMethod independent, for integration tests I even create a new database for each method. If you need to build some data for each test use an "Init" method. Use mocks to isolate the class your testing from it's dependencies.

I always think "what's the minimum amount of code I need to write to prove this works for all cases ?"

Over the last year I have become more and more convinced of the benefits of TDD. The things that I have learned along the way: 1) dependency injection is your friend. I'm not talking about inversion of control containers and frameworks to assemble plugin architectures, just passing dependencies into the constructor of the object under test. This pays back huge dividends in the testability of your code. 2) I set out with the passion / zealotry of the convert and grabbed a mocking framework and set about using mocks for everything I could. This led to brittle tests that required lots of painful set up and would fall over as soon as I started any refactoring. Use the correct kind of test double. Fakes where you just need to honour an interface, stubs to feed data back to the object under test, mock only where you care about interaction. 3) Test should be small. Aim for one assertion or interaction being tested in each test. I try to do this and mostly I'm there. This is about robustness of test code and also about the amount of complexity in a test when you need to revisit it later.

The biggest problem I have had with TDD has been working with a specification from a standards body and a third party implementation of that standard that was the de-facto standard. I coded lots of really nice unit tests to the letter of the specification only to find that the implementation on the other side of the fence saw the standard as more of an advisory document. They played quite loose with it. The only way to fix this was to test with the implementation as well as the unit tests and refactor the tests and code as necessary. The real problem was the belief on my part that as long as I had code and unit tests all was good. Not so. You need to be building actual outputs and performing functional testing at the same time as you are unit testing. Small pieces of benefit all the way through the process - into users or stakeholders hands.

Just as an addition to this, I thought I would say I have put a blog post up on my thoughts on getting started with testing (following this discussion and my own research), since it may be useful to people viewing this thread.

"TDD – Getting Started with Test-Driven Development" - I have got some great feedback so far and would really appreciate any more that you guys have to offer.

I hope this helps! :)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top