Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing Actual Procedure [closed]

Tags:

c

unit-testing

I'm involved in a C project which did not have unit testing during its development. What my superior is asking me is to do bug fixes and create unit tests for the parts which involved modifications. This is also my first time creating tests since I'm also a newbie so he gave me a document describing the procedures.

He said to check the flow control in the function I modified (say func()) and gave a sample test case which goes something like this:

func(int a)  
{  
 if(a == 5)
    ifblock();
 else
    elseblock();
}

1.) input:5, check if flow will go to ifblock()
2.) input:6, check if flow will go to elseblock()

Now the real function involves a more complex condition check compared to the sample but this only for discussion.

My problem is that I do not see the benefit of doing this particular kind of test case (I'm not against unit testing to clarify. just this particular example) so I told him my reasons:
1.) This kind of checking does not prove the function's correctness
2.) I have to create another test case if the code changed even if input and output of function is still the same.
3.) Waste of time especially when I have maybe a hundred similar test cases
4.) From what I read, it seems a function is what is referred to as a unit so no point going line by line (I can see the point in assembly language though)

What I plan to do is to have a set of inputs that will target the modification/specification and check output which simpler and reusable.

He doesn't budge with his instructions but cant explain to me the importance of this one. So if anyone could enlighten me with this since I'm still a newbie and maybe just can't see its value as of this moment.

like image 409
hughes03 Avatar asked May 19 '26 20:05

hughes03


1 Answers

Unit tests are the safety net for further modifications to the code. Some code is easier to test, some is more complicated. In your case of if/else could be interpreted as the definition of the behavior of the system that you have on your hands, which is it's specification.

You can write your unit test as such (specification), and maybe it will help you in understanding the value of such a test. It might seem that you're merely repeating the code that you're trying to test, but if you strive for simplicity and completeness of your tests, you might later be able to throw the implementation, and create a newer, cleaner one.

As you're intending to modify code, that is exactly what your unit tests will be for - defining what was there before, and specifying what is new and what has changed, as you go about changing what's already there.

It is not possible to generalize and give a one-sentence answer to your discourse, and it all depends on too many things - on the desired fate of the software in question, on your willingness to become better at what you do, on the actual state of software you're dealing with, etc.

There are some books that might help you and your boss have solid reasons for writing tests:

  • "Clean Code" & "Clean Coder" by Robert C. Martin
  • "Refactoring" by Martin Fowler, Kent Beck, John Brant and William Opdyke
  • "Test Driven Development: By Example" by Kent Beck
  • "Working Effectively with Legacy Code" by Michael Feathers

As for the bullet points:

  1. It depends on how one writes the test, and what is considered as "correct". If you define as correct a list of inputs and valid outputs (or ranges thereof), then a test that checks exactly that is the "proof"
  2. Why? You'll have to create another test case if you change or extend the function's behavior. If you're not changing it, you shouldn't have to touch the test
  3. Consider data driven testing, in case you're merely checking ranges of inputs and outputs
  4. What do you mean by going line by line? There's a concept of "coverage", meaning that your test exercises a certain portion of your code (statement by statement is a better view than line by line, perhaps). You might want to increase that metric when you write your test

P.S.

What I plan to do is to have a set of inputs that will target the modification/specification and check output which simpler and reusable.

that is data-driven testing

The reason for checking the code line by line may have a very pragmatic reason. You might think of the function as a simple black box with inputs and outputs. You may then create a table for your data-driven test, and run the test, measuring the code coverage. You might even get surprised, that a lot of code is not being hit at all. It might be wise to assume that all lines of code initially had some reason, otherwise they wouldn't be in that function. Trying to discover the reasons behind each line of code (explorative unit testing) can create an even more solid safety net for further refactoring and extensions, at the same time, increasing your understanding of the code.

P.P.S. Another consequence of trying to write the tests may be that you find the code to be obscure, outdated and not very well-written. In that case, you might want to throw the implementation all together, relying only on the specification tests for a complete rewrite.

like image 137
Dmitry Ledentsov Avatar answered May 22 '26 10:05

Dmitry Ledentsov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!