4 ms·
> I know it's cool to "hate" on OO, but "just read the fucking file" doesn't work if you want to run your unit tests without reading a fucking file. Then don't
by burnte 2y ago
> I know it's cool to "hate" on OO, but "just read the fucking file" doesn't work if you want to run your unit tests without reading a fucking file.
Then don't do that, if in the real world it'll read a fucking file, then test with reading a fucking file. Tests aren't there to just be passed, they're to catch problems and if they're not testing the same workflows that the code will see IRL then the test is flawed. The first test should be reading a fucking file and that fucking file could be full of all sorts of garbage.
Same goes for non-fucking files.
- jessekv 2y agoYeah modeless software is one honking great idea. (RIP Larry Tesler)
- xnorswap 2y agoThose are integration tests. Integration tests are great, but not when you want to run thousands of them in a few minutes. And not when you want to have lots running in parallel, accessing and potentially making "changes" to the same files. I'm happy to have a long running integration test suite that runs on a build server. But while working on a project, I need fast running unit tests that I can edit and run to get fast feedback on my work. I find that "time to iterate" is key to effective and enjoyable development. That's why hot module reloading is an amazing innovation for the front-end. The back-end equivalent is quickly running affected unit tests. So I'd rather unit test my FooFileReader to make sure it can read parse (or not) what's in various files, and unit test my service which consumes the output of my FooFileReader by either parameterising the FooFile result or having an IFooFileReader injected. ( Either works to separate concerns. ) While unit testing, I'm going to test "given that System.IO.File can read a file", and write tests accordingly. I don't want a test sometimes fails because "read errors can happen IRL". That doesn't help test my business logic. I can even test what happens if read failures do happen, because I can mock my mock IFooFileReader to return a FileNotFoundException or any other exception. I'd rather not have to force a real-world scenario where I'm getting such an error. In a functional world, it's the difference between: function string -> result and function string -> parsedType -> result The second is cleaner and neater, and you can separately test: function string -> parsedType function parsedType -> result The second is more testable, at the cost of being more indirect. Interfaces and factories are just an idiomatic .NET way of doing this indirection over services and classes. Of course you can also write more in a functional style, and there are times and places to do that too.
- consp 2y agoUnit test are nice to have if you want to make test coverage or have sufficient time to implement them properly. In practice they contain only vague assumptions (the test passes, but the integration stops due to those assumptions being false) or contain things any basic code review should catch (and if you keep paying peanuts they won't do that so you make more unit tests).
- jessekv 2y agoA good interface is testable, this is how you build up reliable abstractions to solve higher level problems. The devs on my team that take shortcuts here waste more time in the end. There is no cost trade-off.
- miningape 2y agoIn most cases especially for important code paths I agree. There is a case where I think it is justifiable to not write a single test: Startups. Specifically pre-seed & seed round funded I think are allowed to skip the majority of tests - however critical paths, especially those that are important to customers (i.e. transactions) must be tested. By the time you have built out that mvp and have a few customers then you should transition to writing more tests. And as the number of engineers, scope, or complexity grows you need to add tests.
- CamperBob2 2y agoIt's testable right up until the point where it's asynchronously interactive. Would unit tests have avoided the Therac-25 incident?
- wtallis 2y ago> While unit testing, I'm going to test "given that System.IO.File can read a file", and write tests accordingly. I don't want a test sometimes fails because "read errors can happen IRL". That sounds pretty squarely in the "you ain't gonna need it" category. If your test harness cannot make a temporary directory and populate it with a copy of the test config file that's stored in the same SCM repo as the test case code, then you simply have a broken CI server. There's no need to complicate your codebase and make your tests less realistic all to avoid hypothetical problems that would almost certainly break your test suite before the test case gets around to attempting an fopen. Just read the damn file. There are more complicated instances where mocking and dependency injection is needed. "fopen might fail on the CI server" usually isn't one of them.
- scrapcode 2y agoYeah, that's called a fucking integration test.
- miningape 2y ago> Tests aren't there to just be passed, they're to catch problems So many developers don't understand this simple concept - it manifests in 2 ways: 1. Not writing tests 2. Writing too many / too specific tests Testing should always be focussed on the OUTCOMES never the implementation. That's why they're so good for making sure edge cases are covered - since we are able to assert the input and expected outcome of the code. I like to use the mental image that in an ideal world I could put the same tests on a completely separate implementation and it would still pass (mocks/stubs, and implementation specific tests don't pass this). I'm always far more frustrated by 2 than by 1 - since 2 adds so much unnecessary code / complexity that doesn't need to be there, growing technical debt through the tool that should help us manage it. They make changing implementations painful. And worst of all they think they're doing something correctly and when combined with the sunk-cost fallacy they're incredibly resistant to changing these fucked up tests. Don't get me wrong 1 is annoying too but he'll at least add the tests when you ask him to and not over engineer everything.
- IggleSniggle 2y agoThere's a lot of room for nuance. If you "just read the fucking file" but the file isn't a "real" configuration file then isn't it just a "mock?" If you replace all network calls with an interceptor that forwards all calls and responses, and just check what's happening as a "listener," aren't you mocking out the network calls to a non-real implementation? At the end of the day, tests are necessarily a mock-up of what's real. You just happen to disagree with where some people put the abstraction layer. I also would like to make my tests more "real" but I have a lot of sympathy for folks that are trying to test something smaller without involving eg a file. After all, the whole point of "everything is a file" in Unix is that we shouldn't need to worry about this detail, it's an OS concern. If you write to a file that's not actually a file on disk but actually a device, that it should fundamentally be okay and work as expected.
- miningape 2y agoYeah don't get me wrong, I'm not anti-mock - real code is messy, and the ideal of the same tests running everywhere will never work, so mocks are necessary. But I do think there's a lot more harm from over-mocking, than under-mocking. > file isn't a "real" configuration file then isn't it just a "mock?" I want to say "no" but I haven't thought about it enough yet. My reasoning is that the file itself contains information about the expected messages to/from systems, since it is the body of whatever the system should respond to. And while it is only 1 layer separated from just creating the same object in memory for your test this "feels" different because you can't just pull it out of your codebase into curl.