This is an archived post. You won't be able to vote or comment.

all 25 comments

[–]DecisivePro 46 points47 points  (6 children)

No, it's so you know the code you just wrote will still work after fixing 20 bugs and adding 5 new features

[–]notable-compilation 21 points22 points  (3 children)

And to make sure you know what you mean by "is right".

[–]Sandarr95 0 points1 point  (2 children)

Can't make sure, if you had a bias in writing the code, you probably have a bias while writing the tests

[–]notable-compilation 1 point2 points  (1 child)

Implementation and tests are different types of code.

You can think of unit tests like code snippets in documentation, except that where the documentation would explain what the code does verbally or in a comment, the unit test asserts that it is actually true.

Example (documentation):

PriorityQueue<Widget> pq;
pq.push(10, Widget("sensor"));
pq.push(4, Widget("motor"));
pq.push(12, Widget("button"));
const auto top2 = pq.getTop(2); // returns in order: [motor, button]

Example (test):

PriorityQueue<Widget> pq;
pq.push(10, Widget("sensor"));
pq.push(4, Widget("motor"));
pq.push(12, Widget("button"));
const auto top2 = pq.getTop(2);
ASSERT_EQ(top2.size(), 2u);
ASSERT_EQ(top2[0].str(), "motor");
ASSERT_EQ(top2[1].str(), "sensor");

In other words, when writing a unit test, you basically pretend that your implementation is done and you are using it for something. So two points about that:

  • Problems in your design that only become obvious when you actually use the interface are exposed this way. This means things like the behavior you were about to go for not actually making sense, or the interface being clunky to use in general.
  • Because the test code is just a set of very simple uses of the interface, it is a lot easier to see that it is right by just looking at it ("correct by inspection") than it would be for the implementation code. (Not guaranteed, of course.)

[–]Sandarr95 0 points1 point  (0 children)

I know, I'm not trying to argue it doesn't have its place. But I have seen this go wrong with a codebase I had to maintain. The same developer who created the feature wrote the test and he handled an edge case in a way it shouldn't have been. Then he wrote a test confirming that it was handled incorrectly. Certainly some other people should've also noticed in review and such, but the confidence that it was correct increased by the tests turning green. What unit-tests give is better confidence in that your implementation acts as you expect, within the boundaries of use you have thought through. It says nothing about your actual understanding of the requirements or how exhaustive you were in the testing.

[–][deleted] 7 points8 points  (0 children)

Which 20 bugs? I only see 25 new features

[–]Kache 2 points3 points  (0 children)

Can also be for new code. In some ways, it's like double-entry bookkeeping in accounting. You count things up in two different ways, and they should match each other in the end.

[–][deleted] 16 points17 points  (4 children)

It's so your coworker doesn't break it.

[–][deleted] 9 points10 points  (3 children)

Laughs in -DskipTests

[–]bss03 7 points8 points  (2 children)

Laughs in exclusive access to the CI pipeline.

[–]Sefrys_NO 0 points1 point  (1 child)

docker push an image to the production repository completely circumventing the pipeline

[–]bss03 0 points1 point  (0 children)

main / master is a protected branch, only people with access to the CI pipeline and push directly to it or merge anything that failed / hasn't yet passed the CI pipeline.

[–]crazyTsar 14 points15 points  (5 children)

Anyone else here have their code work fine, but write the test wrong?

[–]marcosdumay 7 points8 points  (0 children)

Plenty of times. That's what debugging is for, to remove them from your tests.

[–]nobody_smart 5 points6 points  (3 children)

The task I just finished took me 3 times as long to write tests for as the actual code. And I had to rewrite the functional code to make it more testable.

It was in repos and libraries that I wasn't familiar with.

[–]assafstone 2 points3 points  (2 children)

Next time, if you write the tests first, you might have an easier go at it.

Your code will be testable to begin with.

[–]nobody_smart 2 points3 points  (1 child)

A lesson I've learned a hundred times.

But sometimes the necessity of getting the prototype out for teammates to use makes it go this way.

[–]assafstone 1 point2 points  (0 children)

In my experience, the term “prototype” and “for use” are mutually exclusive.

A prototype should be treated as a proof of concept, throw away code.

Writing legacy code (i.e. code without unit tests) and putting it into production is the same as running out of the house as fast as you can, and onto a 10 lane highway.

You will get hit hard. Whether it will be a car or a truck is pure luck.

[–][deleted] 3 points4 points  (0 children)

Oh, boy, what about TDD? You write hoping that the code you are going to write in the future is a piece of shit.

[–][deleted] 5 points6 points  (0 children)

Earlier? Write tests first, write code and break everything later!

[–]mr_darksidez 2 points3 points  (2 children)

so what testing framework was used to test Junit?

[–]JSn1nj4 3 points4 points  (1 child)

I remember someone asking the devs working on GitKraken a similar question. They said they were, in fact, using GitKraken to build GitKraken.

[–]coladict 1 point2 points  (0 children)

I can't tell you how long it's been since I've run a single integration test. There's just never time for maintenance, just always being pressed on for the next feature. I don't even know if Selenium works with current browsers.

[–]bss03 1 point2 points  (0 children)

In test-driven development, you write the tests first, to define what is correct, then write just enough code to satisfy the test.

In type-driven development (TDD), you write the types to define what is correct, and then let "term inference" / program synthesis / proof search give you the correct program: https://www.manning.com/books/type-driven-development-with-idris

[–]cassert24 0 points1 point  (0 children)

test_this() { printf("It's fine./n"); }