How deep are your unit tests?

2019-01-01 07:24发布

The thing I've found about TDD is that its takes time to get your tests set up and being naturally lazy I always want to write as little code as possible. The first thing I seem do is test my constructor has set all the properties but is this overkill?

My question is to what level of granularity do you write you unit tests at?

..and is there a case of testing too much?

17条回答
与风俱净
2楼-- · 2019-01-01 08:07

I don't unit tests simple setter/getter methods that have no side effects. But I do unit test every other public method. I try to create tests for all the boundary conditions in my algorthims and check the coverage of my unit tests.

Its a lot of work but I think its worth it. I would rather write code (even testing code) than step through code in a debugger. I find the code-build-deploy-debug cycle very time consuming and the more exhaustive the unit tests I have integrated into my build the less time I spend going through that code-build-deploy-debug cycle.

You didn't say why architecture you are coding too. But for Java I use Maven 2, JUnit, DbUnit, Cobertura, & EasyMock.

查看更多
高级女魔头
3楼-- · 2019-01-01 08:08

Write unit tests for things you expect to break, and for edge cases. After that, test cases should be added as bug reports come in - before writing the fix for the bug. The developer can then be confident that:

  1. The bug is fixed;
  2. The bug won't reappear.

Per the comment attached - I guess this approach to writing unit tests could cause problems, if lots of bugs are, over time, discovered in a given class. This is probably where discretion is helpful - adding unit tests only for bugs that are likely to re-occur, or where their re-occurrence would cause serious problems. I've found that a measure of integration testing in unit tests can be helpful in these scenarios - testing code higher up codepaths can cover the codepaths lower down.

查看更多
余生无你
4楼-- · 2019-01-01 08:11

Test Driven Development means that you stop coding when all your tests pass.

If you have no test for a property, then why should you implement it? If you do not test/define the expected behaviour in case of an "illegal" assignment, what should the property do?

Therefore I'm totally for testing every behaviour a class should exhibit. Including "primitive" properties.

To make this testing easier, I created a simple NUnit TestFixture that provides extension points for setting/getting the value and takes lists of valid and invalid values and has a single test to check whether the property works right. Testing a single property could look like this:

[TestFixture]
public class Test_MyObject_SomeProperty : PropertyTest<int>
{

    private MyObject obj = null;

    public override void SetUp() { obj = new MyObject(); }
    public override void TearDown() { obj = null; }

    public override int Get() { return obj.SomeProperty; }
    public override Set(int value) { obj.SomeProperty = value; }

    public override IEnumerable<int> SomeValidValues() { return new List() { 1,3,5,7 }; }
    public override IEnumerable<int> SomeInvalidValues() { return new List() { 2,4,6 }; }

}

Using lambdas and attributes this might even be written more compactly. I gather MBUnit has even some native support for things like that. The point though is that the above code captures the intent of the property.

P.S.: Probably the PropertyTest should also have a way of checking that other properties on the object didn't change. Hmm .. back to the drawing board.

查看更多
后来的你喜欢了谁
5楼-- · 2019-01-01 08:11

I make unit test to reach the maximum feasible coverage. If I cannot reach some code, I refactor until the coverage is as full as possible

After finished to blinding writing test, I usually write one test case reproducing each bug

I'm used to separate between code testing and integration testing. During integration testing, (which are also unit test but on groups of components, so not exactly what for unit test are for) I'll test for the requirements to be implemented correctly.

查看更多
宁负流年不负卿
6楼-- · 2019-01-01 08:11

So the more I drive my programming by writing tests, the less I worry about the level of granuality of the testing. Looking back it seems I am doing the simplest thing possible to achieve my goal of validating behaviour. This means I am generating a layer of confidence that my code is doing what I ask to do, however this is not considered as absolute guarantee that my code is bug free. I feel that the correct balance is to test standard behaviour and maybe an edge case or two then move on to the next part of my design.

I accept that this will not cover all bugs and use other traditional testing methods to capture these.

查看更多
零度萤火
7楼-- · 2019-01-01 08:14

I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence (I suspect this level of confidence is high compared to industry standards, but that could just be hubris). If I don't typically make a kind of mistake (like setting the wrong variables in a constructor), I don't test for it. I do tend to make sense of test errors, so I'm extra careful when I have logic with complicated conditionals. When coding on a team, I modify my strategy to carefully test code that we, collectively, tend to get wrong.

Different people will have different testing strategies based on this philosophy, but that seems reasonable to me given the immature state of understanding of how tests can best fit into the inner loop of coding. Ten or twenty years from now we'll likely have a more universal theory of which tests to write, which tests not to write, and how to tell the difference. In the meantime, experimentation seems in order.

查看更多
登录 后发表回答