1. Describe the behavior of the function in a readme with a code example.
2. Create a test that is mostly just a copy/paste from the readme code.
3. Write the actual function until it passes the first test.
4. Write a few more tests for any edge cases I can think of.
5. Get the function to pass again.
6. Encounter another edge case, goto 4.
It seems to work pretty well for me anyway. I think a lot of the debate really centers around unit tests vs integration tests (no one serious I know of is arguing for no testing, or all manual testing).
In my experience, you get the most bang for your buck with mostly unit tests in library code, and mostly integration tests in applications. Despite the difference in use cases, I think both sides talk past each other most of the time.
Unit tests all over the place in an application code tends to be a waste, because the tendency is to test the libraries your application is using. Integration tests in library code is often terrible, because they are usually slower and tightly coupled to external libs.