Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Lately I've been writing some 3D graphics code in Rust for fun. Almost twenty years ago, in highschool, I used to write similar code in C++, without relying on any sort of automated testing – and damn, with the amount of math involved, it's so nice to just write and run some rudimentary sanity-checking tests as you code! I used to rely on constantly building and running some interactive test app and from its behavior try to figure out whether your matrix calculations have a sign error somewhere or not.

A solid type system helps a lot in making refactoring a less fearsome endeavour, but a reasonable test coverage on top of static checking makes it even more so.

Also, automatic perf tests that keep track of regressions and improvements are just awesome.



Sure, this also makes sense when it is about math. But what I write mostly is about managing files on the disk, querying databases, processing text and XML and also some web frontend. Occasionally even communicating via a COM port. And when I need math I do it with NumPy. These tasks seem rather easy to implement and rather hard to test.


You can do some mocking to validate your error handling, definitely check it out.


Mocking sounds like a lot of work. Am I wrong?


Sometimes mocking, even to check error paths, isn't a lot of work. It depends.

A lot of times designing your interfaces to support mock objects more easily improves them in other ways; if you pass in a file object instead of a filename, for example, not only does it become easier to pass in a mock object that raises an error, but it also becomes easier to pass in a GzipFile object or an HTTPResponse object, and presto, your function now handles compressed data and data stored on a web server.

Also, though, monkeypatching stuff in tests isn't hard in dynamic languages. Here's an example from https://echohack.medium.com/python-unit-testing-injecting-ex...:

    with patch.object(requests, "get") as get_mock:
        with nose.tools.assert_raises(socket.error):
            get_mock.side_effect = socket.error
            inject_exception.call_api("http://example.com")


Depends on how you write your code.

If your functions have lots of hidden dependencies and side-effects, it’s hard to test.

If you split concerns properly and keep your glue/IO code separated from the decision-making/business-rules/logic, mocking is quite trivial, and there are advantages other than just testability.

Check out this talk to see examples of that in action: https://www.destroyallsoftware.com/talks/boundaries




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: