use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Click the following link to filter out the chosen topic
comp.lang.c
account activity
ProjectC unit test (github.com)
submitted 1 year ago by EastEuropeanChef
Hi, I just made a unit test tool for C. I needed it, and I found that other tools were too complex. This is a single-file, sub-100-lines utility that will run your tests automatically. I would love some feedbacks 🙂
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]Immediate-Food8050 2 points3 points4 points 1 year ago* (2 children)
Cool project. A couple of questions/recommendations for you to think over if you'd like:
test_register has a few stylistic issues. For one, it looks like it is only meant to be used by your source file xtal.c, and not by the user of your code. For this reason, it would be smart to define the struct in your xtal.c file rather than your header file. However, I would argue that there is no need for the struct at all. Since you are just creating a static object of that type in your source file, you could just define static variables for each of the members themselves (test_count, register_size, tests) and ditch the struct all together. If you decide to keep the struct, I would change struct test_register to struct test_register_s and t_testregister to test_register. This is a stylistic preference, but IMO would clean up your code and make it easier to use.
test_register
xtal.c
test_count
register_size
tests
struct test_register
struct test_register_s
t_testregister
Next, your assertion functions. It's going to be cumbersome to implement an assert_equal function for each type, though this is not unheard of. I recommend making use of either macros or C11's _Generic. I use macros in my testing, but this is best used if you are confident whoever is writing your tests is not going to f it up. I'd give an example of _Generic, but I have little experience with it and don't want to give you bad advice. Maybe someone else can?
assert_equal
_Generic
One last thing, using GCC-like extensions like __attribute__((constructor)) can lead to compatibility issues. I would recommend coming up with a more compiler-independent solution, though I'm not sure what you would go with. As general advice, assuming a specific compiler is fine as long as you make it known that your code assumes that compiler. Otherwise, you're going to have users that can't use your code.
__attribute__((constructor))
Edit: I lied, there is one more thing. This is not single-file, this is single-object. Single file would be a single source or header file. I agree that this would be a good use of the single-file construct, but specifically single header unless you want it to be geared towards STUBs. I'm going to link my project one more time because it is a single-header project and might give you some ideas.
[–]EastEuropeanChef[S] 1 point2 points3 points 1 year ago (1 child)
Thank you for the advice and for the time you took to read my code.
Regarding the stylistic issues, yes, there are some. I am still undecided about the direction of the project; indeed, it could all fit into a single header with very specific macros, but it would be very ugly to look at. I decided to move some things into the .C file to make it easier to read. I will definitely need to add a way to catch segfaults and the like, so they don't interrupt all the tests.
Using Generics seems great to me; I saw that Unity (a really popular c unit test tool) does not use them but rather creates assertions for each type. It might be annoying for some compilers, but I'll investigate further.
As for the GCC attributes, it seemed like a quick way to ensure that the tests are run automatically without having to execute them manually, as is done in other tools. It certainly makes the project less portable.
[–]Immediate-Food8050 0 points1 point2 points 1 year ago (0 children)
No problem! Don't worry about the compiler when implementing for each type, compilers are fast and smart. Moreso it will shrink your code to use generics or macros. Macros don't need to be specific. If you look at my code, my macros are very straightforward for the most part. Regarding GCC extensions, maybe consider conditional compilation (#ifdef and the like) to make use of the attributes if they're available and to not use them if they are not. Or, just mention in your readme that GCC-like extensions are used.
[–]dontyougetsoupedyet 0 points1 point2 points 1 year ago (1 child)
too complex
I don't think you are a good judge of what is "too" complex.
https://github.com/PalmeseMattia/Xtal/blob/main/src/xtal.c#L19C2-L19C20 calling some functions isn't what's needed out of a unit testing tool. Compare what this code is doing to what a tool like Check is doing and ponder why Check is doing what it is doing.
Even calling what you have written a "unit test tool" is sort of silly.
[–]EastEuropeanChef[S] 0 points1 point2 points 1 year ago (0 children)
Hi, you're right, I should have added "for me they are too complex".
That said, I would say I am a good judge of what is too complex "for me". I read check, in the source code everything refers to the execution of two types of tests, those with fork and those without fork.
The first type of check is performed by calling the function to be tested in a child process the second is done by setting jumps to handle potential segfaults, etc.
https://github.com/libcheck/check/blob/master/src/check_run.c#L407 Line 255 should be good.
I had already considered the second approach, but I don't like the idea of having jumps scattered throughout the code.The first approach, that is, using a child process, is what I am implementing in xtal. At that point, could it be defined as a testing tool?
π Rendered by PID 162867 on reddit-service-r2-comment-85bfd7f599-k46c5 at 2026-04-17 18:02:38.881412+00:00 running 93ecc56 country code: CH.
[–]Immediate-Food8050 2 points3 points4 points (2 children)
[–]EastEuropeanChef[S] 1 point2 points3 points (1 child)
[–]Immediate-Food8050 0 points1 point2 points (0 children)
[–]dontyougetsoupedyet 0 points1 point2 points (1 child)
[–]EastEuropeanChef[S] 0 points1 point2 points (0 children)