5 ms·
> the high level requirement that buying 10 of something should be cheaper than 9 is just specified system behaviour and that is exactly what you should be tes
by paranoidrobot 6y ago
> the high level requirement that buying 10 of something should be cheaper than 9 is just specified system behaviour and that is exactly what you should be testing for.
But that is an implementation detail. Only the BulkPurchaseDiscountStrategy knows whether it's 9 or 10 that's the trigger. Maybe it varies based on time of day or for certain customers.
> I would refer to these tests as "integration tests" although the language is poor here.
Agreed, it's a discussion I'm having at my job now, I havn't found particularly great wording. "Functional" testing still doesn't quite work right.
> Integration tests do not replace unit tests, they should just be taking a lot of the load.
Agreed on the first part. Integration tests are valuable, but I think they're more fragile.
Writing them is, IMO/IME, slower and more difficult.
As for the linked tweet, it's the "mostly integration" part that I disagree with.
- rkangel 6y ago> But that is an implementation detail. Only the BulkPurchaseDiscountStrategy knows whether it's 9 or 10 that's the trigger. Language is poor, but I think there is consensus on what "implementation detail" means, and I don't think that's it. Whether it's 9 or 10 is customer facing behaviour. It's behaviour that might come from your marketing team or product owner or whatever, but it is outward facing. It is something that someone could write in a word document and call part of your specification. The implementation detail would be whether that logic lives in BulkPurchaseDiscountStrategy or as one case in a big ShoppingCart class. A user pressing buttons on your UI can see the result of the price break, but they can't see the difference in code organisation. You can say "price breaks should occur at 9 items" without ever saying "BulkPurchaseDiscountStrategy". In one ideal, all tests would test user facing requirements and not know anything about your code. You could refactor your code to your heart's content and know you the result was still what you wanted. There are downsides to that though because those end to end or system tests are fragile to write and expensive to run. It's much easier to cover all possible code paths with more focused testing. Hence in this case you could test the top interface of ShoppingCart, with all it's assembled dependencies. Not the same as pushing button in a Web Browser, but a lot more convenient to write and run.
- bluGill 6y agoBut the price break is a requirement that I expect to change. Today it is 10. Tomorrow someone looks at the production process the machines give groups of 11, so the bulk discount should be multiples of 11 (if you order 12 you get 11 at the bulk rate and 1 and the regular price). Then next week management says small orders are too hard to serve, and so the minimum bulk order is 100, but bigger discounts if the total order is a multiple off 11. Then the week after... Point is that your implementation of the discounts is expected to change. I should not have to change my shopping cart tests at all just because the discount requirement changed - it makes the costs of those tests too high. Of course this is domain specific. I expect discounts to change all the time. Likewise I expect taxes to change often. In both cases they need to be mocked/faked just to keep my test code sane. there are many other domain specific things that won't change. I'm always going to store the shipping mass in KG, and for some customers convert it to lbs. It is reasonable to hardcode the weight in lbs as that won't change. (future me who has to ship to mars will disagree, but I don't know what the requirements are)
- rkangel 6y agoIf your requirement changes so that the price break is at 11 rather than 10, then I expect the process to go: * Change the (or shared test code) that has the price break specification from 10 to 11 * Run it, see the failures * Update the source code appropriately The updated source code is the same in both our cases. In my case the changed test code is testing the ShoppingCart interface and in yours it's a unit test of something lower down. There's not extra cost, it's just in a different place. Or are you suggesting that your tests don't know about 10 vs 11 at all? There's a reasonable architecture where such data comes from outside your system, and the spec for your system is 'price breaks should reflect this data input' and then you mock that data input and test it, but that's a different thing.
- bluGill 6y agoI'm saying the discount code tests have the change from 10 to 11. this entire thread isn't about the discount code tests though it is about the shopping cart. There is a lot more to calculating price than just discount codes, tax rates for example. The cart needs to show regular price, the discount, the tax, shipping costs, and then total. Each of those is tested for multiple edge cases, so if we do it all in the shopping carts there are potentially hundreds of unrelated tests that need to change when the discount factor changes just because they happen to check the total.