• nous@programming.dev
    link
    fedilink
    English
    arrow-up
    3
    ·
    10 months ago

    Honestly, I don’t think unit tests are a useful name. Everyone has a different idea of what a unit is and the line between unit tests and integrations tests is IMO not very useful. As long as your tests are

    • isolated from external factors (ie they completely control the test environment),
    • fast to run
    • repeatable, aka not flaky
    • can identify problems easily

    Then where you draw the line between unit and integration is meaningless. It was meant to be that ingratiation tests were slow, so you wanted to shrink them down to make them faster to run. But I have not had a problem with the speed of more integration style tests in a long time.

    I also don’t think interacting with the OS is such a bad idea. For instance the filesystem (what everyone always points to as an example) IMO is fine if done right. The big issue with interacting with the FS is keeping your tests isolated - too many people end up reading/writing the same file locations and thus breaking isolation. But you can always create a unique tmp dir for each test and do what ever you want inside that. Interacting with the filesystem on modern system is fast, and reliable - especially given that tmp locations are generally in ram these days.

    I think the better term you are looking for is mocks and mocking. IMO these should be kept to a minimum. Like the above - you dont need to mock out the filesystem API when you can just use the filesystem in an isolated way. Same with network services - I really like gos httptest module, it lets you easily spin up a webserver that you can respond with whatever you need to. No need to create a mockable API when you can spin up a fast and reliable http endpoint to respond how you need it to.

    Which leads to fakes (ie fake, simple implementations of a real external API). IMO these are far more useful than mocks and should be your first resort with mocks being your last resort. Such as things like gofakes3 an in memory s3 implementation in go that you can use any s3 client to talk to. Things like this let you create tests that you spin up the server (a unique one for each test), put objects into it to set things up how you need them, run your function and assert the contents are what you expect. Makes your tests more complete (and that you are not just testing your mock implementation rather than your actual logic) while keeping them isolated and fast - all the benefits of a small unit test combined with the wider scope of an integration test.

    • jpeps@lemmy.world
      link
      fedilink
      arrow-up
      2
      ·
      10 months ago

      Couldn’t agree more with this comment and the thread in general, it’s a relief to see. I get so frustrated as so many of my colleagues seem to cling to this very old concept of the testing pyramid and associated definitions. It’s completely meaningless in a modern setting. We should mock as little and as far back as possible, yet others seem to delight in locking huge chunks of functionally out of the test base just ‘because’.