How to circumvent `multiple definition of main` for testing

I’m trying to create an ncurses Pomodoro timer application using the C skeleton and minunit.h. When I was writing the timer code, it was fine, because I hadn’t written the main application yet, so I could happily write and execute unit tests. But now as I try to write the ncurses interface, I can only make the main app, not the tests. Attempting to run make tests fails with a multiple definition of main error. I understand that this is because of how the RUN_TESTS macro of minunit.h works. Is there a way to get both working? My search engine skills seem to have failed me, as I can’t seem to find the right search terms to use.

If it’s any help, the Makefile I’m using is here, adapted from the c-skeleton Makefile to work for applications as opposed to libraries.

As a rule of thumb, with this system you can only test things in files that have no main function defined. So what you would do is keep main.c (or app.c or whatever it’s called) as small as possible, importing the stuff that does the work from other files. Then for the tests you import the stuff you want to test from those files but you can’t include main.c as a source file.

If you show us your repository structure we might be able to give you a tip for how to change the Makefile to make it work.

That’s fine. I know that I have to test the interface in main.c by hand. I only wrote the tests for the logic functions that are in src/pomodoro.c; src/main.c` has no tests associated with it.

Here’s the directory structure:

├── bin
│   └── <executable ends up here>
├── LICENSE
├── Makefile
├── README.md
├── src
│   ├── dbg.h
│   ├── long_fanfare.wav // sound playing not yet implemented
│   ├── main.c
│   ├── minunit.h
│   ├── pomodoro.c
│   ├── pomodoro.h
│   └── short_fanfare.wav // sound playing not yet implemented
└── tests
    ├── pomodoro_tests.c
    └── runtests.sh

Side note: the program itself seems to work well, and at some point I’ll probably put a link in the Gallery for others to check it out.

Yes, but main.c is included in the variable for the source files in your Makefile, and so it’s included when you compile the tests. You need to find a way to not have main.c appear in the command that compiles the tests.

Ah, you’re right. I did some Googling and stumbled across the filter-out function in GNU make. Now it works. Thanks for the help!

1 Like
A free service run by Zed A. Shaw for learncodethehardway.org.