I have been writing a C program recently as an exercise for myself- it's an implementation of Newton's method that uses a compiler to turn the user's input from a string representing a mathematical function into a bytecode representing said function and then runs it on a virtual machine. All written by myself using only the C standard library.
I think I have it now, but testing a program by entering a function and seeing whether things blow up is tedious and not very accurate, so I wanted to learn unit-testing. My problem is that every resource I can find only describes using a unit-testing framework. Can anyone explain to me how to do it myself or point me to an article or even a book?
Here is how the project is structured: there is the main source file (newton.c) the contains the main function that ties things together. Then there are different modules in their own sub-directories. Some modules are dependent on others, but for the most part every module is its own thing. The compiler and the virtual machine need to know about the bytecode but they know nothing of each other. Here is the directory structure used:
Code: Select all
Source
|
|- newton.h (common constants like PI)
|- newton.c (main function)
|
|- compiler
| |- compiler.h
| |- compiler.c
|
|- function_deriver
| |- function_deriver.h
| |- function_deriver.c
|
|- lexer
| |- lexer.h
| |- lexer.c
|
|- method (Newton's method)
| |- method.h
| |- method.c
|
|- parser
| |- parser.h
| |- parser.c
|
|- syntax_node
| |- syntax_node.h
| |- syntax_node.c
|
|- syntax_node_stack
| |- syntax_node_stack.h
| |- syntax_node_stack.c
|
|- virtual_machine
|- opcodes.h
|- vm_code.h
|- vm_code.c
|- vm.h
|- vm.c
So how can I test the vm_code units? For the public functions it's simple:
Code: Select all
/** @file Tests/virtual_machine/test_vm_code.c */
#include "../../Source/virtual_machine/vm_code.h"
// this will be exposed to the function running all the tests
int test_vm_code(void) {
int success = 0;
if (success += test_vm_code_new() != 0) {goto end;}
if (success += test_vm_code_copy() != 0) {goto end;}
if (success += test_vm_code_clear() != 0) {goto end;}
end:
return success;
}
static int test_vm_code_new(void);
static int test_vm_code_copy(void);
static int test_vm_code_clear(void);
static int test_vm_code_new(void) {
VMCode code = test_vm_code_new();
return (code.length == 0 && code.code == NULL) : 0 : 1;
}
/* and so on */
Code: Select all
#include "../../Source/virtual_machine/vm_code.c"
So my problem is, how do I hook up my source code that is meant to be one program, to the test code, which will compile into an entirely different program?
Why am I not just using a unit testing framework like everyone else? As I said above, this program is mostly an exercise to myself. I believe before you start using the power tools you should do it yourself first at a smaller scale. Before using autotools one should know how a makefile is built and before using a makefile on should first know how to invoke the compiler. All the resources I could find on unit-testing frameworks were written as if the reader was already expected to know how a unit testing framework works. That kind of defeats the point of it, doesn't it?