blob: 11a81e82e8827ba468df649db2801c57d2a15728 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Adding Unit Tests to a C/C++ Project</title>
<meta name="DESCRIPTION" content="A tutorial for using unit testing in C/++ projects in NetBeans IDE and
Oracle Solaris Studio IDE">
<meta name="keywords" content="NetBeans, IDE, integrated development environment,Oracle Solaris Studio
tutorial, guide, user, documentation, open source, unit testing, CUnit, CppUnit, C, C++">
<meta name="author" content="Susan Morgan"><!--Optional tag-->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" >
<link rel="stylesheet" type="text/css" href="../../../netbeans.css" media="screen">
</head>
<body>
<h1>Adding Unit Tests to a C Project - NetBeans IDE Tutorial</h1>
<!-- START INTRO ---------------------------------------------------------------------------------------* -->
<div class="articledate" style="margin-left: 0px;font-style:italic;">
<p><em>Contributed by <a href="mailto:susanm@netbeans.org"><i>Susan Morgan</i></a>
<br>
June 2010</em> [Revision number: V6.9-1]</div>
<!-- END INTRO -->
<h3>Contents</h3>
<img src="../../../images_www/articles/71/netbeans-stamp-71-72-73.png" class="stamp"
alt="Content on this page applies to NetBeans IDE 7.1, 7.2 and 7.3" title="Content on this page applies to the NetBeans IDE 7.1, 7.2 and 7.3">
<table class="b-none vatop" cellpadding="0" cellspacing="0">
<tr>
<td class="hyphen">-&nbsp;</td>
<td><a href="#requirements">Requirements</a></td>
</tr>
<tr>
<td class="hyphen">-&nbsp;</td>
<td><a href="#intro">Introduction</a></td>
</tr>
<tr>
<td class="hyphen">-&nbsp;</td>
<td><a href="#cunit">Install the CUnit Testing Framework</a></td>
</tr>
<tr>
<td class="hyphen">-&nbsp;</td>
<td><a href="#project">Create the Project for the Tutorial</a></td>
</tr>
<tr>
<td class="hyphen">-&nbsp;</td>
<td><a href="#addtest">Add CUnit Tests to the NetBeans Managed Project</a></td>
</tr>
<tr>
<td class="hyphen">-&nbsp;</td>
<td><a href="#runtest">Run the CUnit Test</a></td>
</tr>
<tr>
<td class="hyphen">-&nbsp;</td>
<td><a href="#addmore">
Add Another CUnit Test</a></td>
</tr>
<tr>
<td class="hyphen">-&nbsp;</td>
<td><a href="#debug">Debug a Test</a></td>
</tr>
<tr>
<td class="hyphen">-&nbsp;</td>
<td><a href="#addsimple">Add a Simple Test</a></td>
</tr>
<tr>
<td class="hyphen">-&nbsp;</td>
<td><a href="#editsimple">Edit the Simple Test</a></td>
</tr>
<tr>
<td class="hyphen">-&nbsp;</td>
<td><a href="#commandline">Run Tests From the Command Line</a></td>
</tr>
</table>
<h2><a NAME="requirements"></a>Requirements</h2>
<p><b>To follow this tutorial, you need the following software.</b></p>
<table>
<tbody>
<tr>
<th class="tblheader" scope="col">Software</th>
<th class="tblheader" scope="col">Version Required</th>
</tr>
<tr>
<td class="tbltd1">NetBeans IDE (including C/C++/Fortran support) </td>
<td class="tbltd1"><a href="https://netbeans.org/downloads/index.html">version 7.1, 7.2 or 7.3 with NetBeans C/C++ plugin</a></td>
</tr>
<tr>
<td class="tbltd1">Java Development Kit (JDK)</td>
<td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">Version 6 or 7</a></td>
</tr>
<tr>
<td class="tbltd1">
CUnit 2.1 test framework
</td>
<td class="tbltd1">
<a href="http://sourceforge.net/projects/cunit/">C Unit Testing Framework project on sourceforge.</a>
</tr>
</tbody>
</table>
<br>
<p>See the <a href="../../../community/releases/73/install.html">NetBeans IDE
7.2 Installation Instructions</a> and <a
href="../../../community/releases/73/cpp-setup-instructions.html">
Configuring the NetBeans IDE for C/C++/Fortran</a><br> for
information about downloading and installing the required NetBeans software.</p>
<a name="intro"></a>
<h2>Introduction</h2>
<p>
NetBeans IDE with the C/C++/Fortran plugin supports unit tests in C/C++ projects.
You can use the IDE to create, run, debug, and view results of your C and C++ tests. This article
shows you how to use unit tests in the IDE with your C/C++ projects.
</p>
<p>A managed project is created with a logical folder called Test Files, where you can manage unit tests for the project.
You can create tests directly under this Test Files folder or organize them in logical sub folders.
A test node in the Test Files folder is a special folder with test-related actions. When a test is built, it will exclude
the main file from the project and otherwise use all other project settings. </p>
<p>For managed projects that you created with a previous version of the IDE, the Test Files folder
does not exist. The Test Files folder is created for your existing projects when you create a test
with the wizard, as described in this tutorial.</p>
<p>
The IDE supports only CUnit, CppUnit and its own "simple" output format, which means your tests should produce
output of one of these types of tests. The IDE provides templates for unit tests:
<ul>
<li>C simple test</li>
<li>C++ simple test</li>
<li>CUnit test</li>
<li>CppUnit test</li>
<li>CppUnit test runner</li>
</ul>
<p>This tutorial uses the CUnit test framework and NetBeans C Simple Tests on Ubuntu Linux, but the techniques demonstrated can help
you with the other types of tests on other platforms as well. The tutorial does not explain the CUnit or
CppUnit testing frameworks. You need to consult the documentation for those frameworks for information
about how to use them.</p>
<h2><a name="cunit"></a>Install the CUnit Testing Framework</h2>
<p>To follow this tutorial, you must install CUnit on your system first. You can download
the CUnit framework from the
<a href="http://sourceforge.net/projects/cunit/">C Unit Testing Framework project on sourceforge.</a></p>
<p>The <a href="http://sourceforge.net/projects/cunit/files">CUnit files page</a> includes
links to binary downloads for Windows and Linux.</p>
<p>For Solaris systems, you must download the CUnit-2.1-0-src.tar.gz source from the <a href="http://sourceforge.net/projects/cunit/files">CUnit files page</a>
and use the <a href="http://en.wikipedia.org/wiki/GNU_build_system">GNU build system</a>
to build the source and install. You can get the GNU build system components autoconf and automake for Solaris
from <a href="http://sunfreeware.com">sunfreeware.com</a>.</p>
<p>The CUnit documentation is included in the CUnit download, or you can view it at
<a href="http://cunit.sourceforge.net/doc/index.html">http://cunit.sourceforge.net/doc/index.html</a>.</p>
<h2><a name="project"></a>Create the Project for the Tutorial</h2>
<p>To explore the unit test features, you should first create a new C Application:
<ol>
<li>Choose File &gt; New Project.</li>
<li>In the project wizard, click C/C++ and then select C/C++ Application.</li>
<li>In the New C/C++ Application dialog box, select Create Main file and select the C language.
Accept the defaults for all other options.<br/>
<img class="margin-around b-all"
src="../../../images_www/articles/73/cnd/c-unit/c-unit-new-project.png" alt="Screenshot of New Project dialog">
</li>
<li>Click Finish, and the Cpp_Application_1 project is created.</li>
<li>In the Projects window, open the Source Files folder and double-click the <code>main.c</code> file to open it in the editor. The file's
content is similar to that shown here:<br/>
<img class="margin-around b-all"
src="../../../images_www/articles/73/cnd/c-unit/c-unit-mainc-initial.png" alt="Screenshot of main.c file before editing">
</li>
<li>To give the program something to do, replace the code in the <code>main.c</code> file with the following code
to create a simple factorial calculator:
<pre class="examplecode">
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
long factorial(int arg) {
long result = 1;
int i;
for (i = 2; i <= arg; ++i) {
result *= i;
}
return result;
}
int main(int argc, char** argv) {
printf("Type an integer and press Enter to calculate the integer's factorial: \n");
int arg;
fflush(stdout);
scanf("%d", &arg);
printf("factorial(%d) = %ld\n", arg, factorial(arg));
return (EXIT_SUCCESS);
}
</pre>
<p>The file should look as follows after editing:</p>
<img class="margin-around b-all"
src="../../../images_www/articles/73/cnd/c-unit/c-unit-mainc-edited.png" alt="Screenshot of main.c file after editing">
</li>
<li>Save the file by pressing Ctrl+S.</li>
<li>Build and run the project to make sure it works by clicking the Run button in the IDE toolbar.<br>
The output should look similar to the following if you enter 8 as the integer:<br/>
<img class="margin-around b-all"
src="../../../images_www/articles/73/cnd/c-unit/c-unit-output-factorial.png" alt="Screenshot of factorial program output">
</li>
</ol>
<h2><a name="addtest"></a>Add CUnit Tests to the NetBeans Managed Project</h2>
<p>When you are developing an application, it is a good idea to add unit tests as part of
your development process.
</p>
<p class="tips">
Each test should contain one <code>main</code> function and generate one executable.
</p>
<ol>
<li>
In the Projects window, right-click the <code>main.c</code> source file and select Create Test &gt; New CUnit Test.<br/>
<img class="margin-around b-all" src="../../../images_www/articles/73/cnd/c-unit/c-unit-create-test.png" alt="Screenshot of creating a new test">
<p>A wizard opens to help you create the test.</p>
</li>
<li>In the wizard's Select Elements window, click the checkbox for the main function. This causes all
the functions within <code>main</code> to also be selected. In this program, there is only one other function, factorial().</li>
<li>Click Next.</li>
<li>Keep the default name New CUnit Test and click Finish.
<p>The New CUnit Test node is displayed under the Test Files folder.</p>
The New CUnit Test folder contains the template files for the test. You can add
new files to the folder the same way you add source files to a project, by right-clicking the folder.
</li>
<li>Expand the New CUnit Test folder, and see that it contains a
file <code>newcunittest.c</code> which should be open in the source editor.</li>
<li>In the <code>newcunittest.c</code> file, notice the #include "CUnit/Basic.h"
statement to access the CUnit library.
The <code>newcunittest.c</code> file contains an automatically generated test function,
<code>testFactorial</code>, for the <code>factorial()</code> function of
<code>main.c</code>.
</li>
</ol>
<img class="margin-around b-all" src="../../../images_www/articles/73/cnd/c-unit/c-unit-includes.png"
alt="Screenshot of newcunittest.c includes">
<p>The generated test is a stub that you must edit to make useful tests, but the generated
test can be run successfully even without editing.</p>
<h2><a name="runtest"></a>Run the C Unit Test</h2>
<p>The IDE provides a few ways to run tests. You can right-click the project node, or the Test Files folder, or a test subfolder, and select Test.
You can also use the toolbar and select Run &gt; Test Project, or press Alt+F6.
</p>
<ol>
<li>Run the test by right-clicking the New CUnit Test folder and selecting Test. The IDE
opens a new Test Results window, and you should see output similar to the following,
which shows that the test fails:<br/>
<img class="margin-around b-all" src="../../../images_www/articles/73/cnd/c-unit/c-unit-run-test-orig.png"
alt="Screenshot of initial test run">
</li>
<li>Notice that the Test Results window is split into two panels. <br>
The right panel displays the console output from the tests. The left
panel displays a summary of the passed and failed tests and the
description of failed tests.</li>
<li>In the Test Results window, double-click the node
<code>testFactorial caused an ERROR</code> to jump to the <code>testFactorial</code> function in
the source editor.
<br>If you look at the function you can see that it does not actually test anything, but merely asserts that
the unit test failed by setting CU_ASSERT(0). The condition evaluates to 0, which is equivalent
to FALSE, so the CUnit framework interprets this as a test failure. </li>
<li>Change the line CU_ASSERT(0) to CU_ASSERT(1) and save the file (Ctrl+S).</li>
<li>Run the test again by right-clicking the New CUnit Test folder and selecting Test.<br>
The Test Results window should indicate that the test passed.<br/>
<img class="margin-around b-all" src="../../../images_www/articles/73/cnd/c-unit/c-unit-run-test-pass.png"
alt="Screenshot of test run after changing CU_ASSERT">
</li>
</ol>
<h2><a name="addmore"></a>Add Another CUnit Test</h2>
<ol>
<li>Create a generic CUnit test template by right-clicking the Test Files folder and selecting
New CUnit Test.<br/>
<img class="margin-around b-all" src="../../../images_www/articles/73/cnd/c-unit/c-unit-new-cunit-test.png"
alt="Screenshot of adding new cunit test to Test Files ">
</li>
<li>Name the test My CUnit Test and the test file name <code>mycunittest</code> and click Finish.<br/>
<img class="margin-around b-all" src="../../../images_www/articles/73/cnd/c-unit/c-unit-create-mycunittest.png"
alt="Screenshot of Create Test wizard">
</li>
<li>A new test folder called My CUnit Test is created and it contains a <code>mycunittest.c</code>
file, which opens in the editor.</li>
<li>Examine the <code>mycunittest.c</code> test file and see that it contains two tests. test1 will pass because it evaluates
to TRUE, and test2 will fail because it evaluates to FALSE since 2*2 does not equal 5.
<pre class="examplecode">
void test1()
{
CU_ASSERT(2*2 == 4);
}
void test2()
{
CU_ASSERT(2*2 == 5);
} </pre>
</li>
<li>Run the test as before and you should see:<br/>
<img class="margin-around b-all" src="../../../images_www/articles/73/cnd/c-unit/c-unit-run-mytest1.png"
alt="Screenshot of pass and fail tests">
</li>
<li>Run all the tests from the IDE main menu by selecting Run &gt; Test Project (Cpp_Application_1) and see
that both test suites run and display their success and failure in the Test Results window.
</li>
<li>Mouse over the failed test to see more information about the failure.<br/>
<img class="margin-around b-all" src="../../../images_www/articles/73/cnd/c-unit/c-unit-test-fail-annotation.png"
alt="Screenshot of annotation for failed test">
</li>
<li>Click the filter button <img src="../../../images_www/articles/73/cnd/c-unit/c-unit-filter.png"
alt="Test filter button"> in the left margin of the Test Results window to show only the failed tests.
</ol>
<h2><a name="debug"></a>Debug My CUNit Test</h2>
<p>You can debug tests using the same techniques you use to debug your project source
files, as described in the
<a href="https://netbeans.org/kb/docs/cnd/debugging.html">Debugging C/C++ Projects Tutorial</a>.</p>
<ol>
<li>In the Projects window, right-click the My CUNit Test folder and select
Step Into Test.
<p class="tips">You can also run the debugger by right-clicking a test in the Test Results window and selecting Debug.</p>
<br>The debugger toolbar is displayed.
</li>
<li>Click the Step Into button
to execute the program one statement at a time with each click of the button.<br/>
<img class="margin-around b-all" src="../../../images_www/articles/73/cnd/c-unit/c-unit-debug-icons.png"
alt="Screenshot of debug stepinto icon">
</li>
<li>Open the Call Stack window by selecting Window &gt; Debugging &gt; Call Stack so you can
watch the function calls as you step through the test.</li>
</ol>
<h2><a name="addsimple"></a>Add a Simple Test</h2>
<p>The C simple test uses the IDE's own simple test framework. You do not need to download any test framework
to use simple tests.</p>
<ol>
<li>
In the Projects window, right-click the <code>main.c</code> source file and select Create Test &gt; New C Simple Test.<br/>
<img class="margin-around b-all" src="../../../images_www/articles/73/cnd/c-unit/c-unit-mainc-new-simple-test.png"
alt="Screenshot of New Simple Test creation">
</li>
<li>In the wizard's Select Elements window, click the checkbox for the main function, then click Next.<br/>
<img class="margin-around b-all" src="../../../images_www/articles/73/cnd/c-unit/c-unit-mainc-new-simple-test-select.png"
alt="Screenshot of Select Elements window of test wizard">
</li>
<li>In the Name and Location window, keep the default name New C Simple Test and click Finish.
<p>The New C Simple Test node is displayed under the Test Files folder.</p>
</li>
<li>Expand the New C Simple Test folder, and see that it contains a
file <code>newsimpletest.c</code>. This file should be open in the source editor.<br/>
<img class="margin-around b-all" src="../../../images_www/articles/73/cnd/c-unit/c-unit-mainc-new-simple-test-folder.png"
alt="Screenshot of New C Simple test folder">
</li>
<li>Notice the <code>newsimpletest.c</code> file contains an automatically generated test function,
<code>testFactorial</code>, for the <code>factorial()</code> function of
<code>main.c</code>, just as with the CUnit test.<br/>
<img class="margin-around b-all" src="../../../images_www/articles/73/cnd/c-unit/c-unit-mainc-new-simple-test-code.png"
alt="Screenshot of New C Simple test code">
<p>The <tt>if</tt> statement should test a condition that, if true, indicates that the test failed. The
<tt>%%TEST_FAILED%%</tt>token triggers display of the graphical indicator of test failures in the Test
Results window. The <tt>if</tt> statement in the generated test sets the condition to be true by setting it to 1,
so the test always fails when you run it unmodified.</p>
<p>The other tokens in the <tt>main</tt> function, such as <tt>%%TEST_STARTED%%</tt> and <tt>%%TEST_FINISHED%%</tt>
are to help you read the command line output when running the tests.</p>
<p>The <tt>time=0</tt> option is used to add time measurement to the test.</p>
<p>The <tt>message</tt> option enables you to make the test print out a message about the test failure.</p>
</li>
<li>Run the test to see that it generates a failure shown in the Test Results window.</li>
</ol>
<p class="note">Next you edit the test file to see tests that pass.</p>
<h2><a name="editsimple"></a>Edit the C Simple Test</h2>
<ol>
<li>Copy and paste a new function below the <code>testFactorial</code> function.
<br>The new function is:
<pre class="examplecode">
void testNew() {
int arg = 8;
long result = factorial(arg);
if(result != 40320) {
printf("%%TEST_FAILED%% time=0 testname=testNew (newsimpletest) message=Error calculating %d factorial.\n", arg);
}
}</pre>
<p>The main function must also be modified to call the new test function.</p>
</li>
<li>In the <code>main</code> function, copy the lines:
<pre class="examplecode">
printf("%%TEST_STARTED%% testFactorial (newsimpletest)\n");
testFactorial();
printf("%%TEST_FINISHED%% time=0 testFactorial (newsimpletest)\n");
</pre>
</li>
<li>Paste the lines immediately below the ones you copied, and change the name <code>testFactorial</code>
to <code>testNew</code> in the pasted lines. There are three occurrences that need to be changed.
<br>The complete <code>newsimpletest.c</code> file should look as follows:
<pre class="examplecode">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
/*
* Simple C Test Suite
*/
long factorial(int arg);
void testFactorial() {
int arg;
long result = factorial(arg);
if(1 /*check result*/) {
printf("%%TEST_FAILED%% time=0 testname=testFactorial (newsimpletest) message=When value is 1 this statement is executed.\n");
}
}
void testNew() {
int arg = 8;
long result = factorial(arg);
if(result != 40320) {
printf("%%TEST_FAILED%% time=0 testname=testNew (newsimpletest) message=Error calculating %d factorial.\n", arg);
}
}
int main(int argc, char** argv) {
printf("%%SUITE_STARTING%% newsimpletest\n");
printf("%%SUITE_STARTED%%\n");
printf("%%TEST_STARTED%% testFactorial (newsimpletest)\n");
testFactorial();
printf("%%TEST_FINISHED%% time=0 testFactorial (newsimpletest)\n");
printf("%%TEST_STARTED%% testNew (newsimpletest)\n");
testNew();
printf("%%TEST_FINISHED%% time=0 testNew (newsimpletest)\n");
printf("%%SUITE_FINISHED%% time=0\n");
return (EXIT_SUCCESS);
}
</pre></li>
<li>In the Projects window, run the test by right-clicking New C Simple Test and choosing Test.
<br>The Test Results should look as follows:<br/>
<img class="margin-around b-all" src="../../../images_www/articles/73/cnd/c-unit/c-unit-simpletest-results.png"
alt="Screenshot of simple test results">
<p class="tips">The %%TEST_FAILED%% token triggers the display of a test failure in the Test Results window.
The if statement should test for a condition that if it is not true, the test fails. </p>
<p class="tips">The %%SUITE_STARTING%% and other similar tokens are not shown in the output in the IDE. They are
used for console output.
</li>
</ol>
<h2><a name="commandline"></a>Run Tests From the Command Line</h2>
<p>
You can build tests from the command line outside the IDE with <code>make build-tests</code> and run them with <code>make test</code>.
When the project is in ~/NetBeansProjects/Cpp_Application_1 on a Linux system,
the examples in this article would be built and run as shown below.
<ol>
<li>Open a terminal window or use the Internal Terminal in the IDE
by selecting Window &gt; Output &gt; Internal (Experminental) and clicking the
Create New Terminal Tab icon.
</li>
<li>In the terminal, type the commands shown in bold:
<pre class="examplecode"><b>cd ~/NetBeansProjects/Cpp_Application_1</b>
<b>make test</b></pre>
<p>The output of the test build and run should look similar to
the following. Note that some <code>make</code> output has been deleted.</p>
<pre class="examplecode">
"make" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf
make[1]: Entering directory `/home/tester/NetBeansProjects/CppApplication_1'
"make" -f nbproject/Makefile-Debug.mk dist/Debug/GNU-Linux-x86/cppapplication_1
make[2]: Entering directory `/home/tester/NetBeansProjects/CppApplication_1'
make[2]: `dist/Debug/GNU-Linux-x86/cppapplication_1' is up to date.
...
CUnit - A Unit testing framework for C - Version 2.1-0
http://cunit.sourceforge.net/
Suite: mycunittest
Test: test1 ... passed
Test: test2 ... FAILED
1. tests/mycunittest.c:33 - 2*2 == 5
Test: test3 ... passed
--Run Summary: Type Total Ran Passed Failed
suites 1 1 n/a 0
tests 3 3 2 1
asserts 3 3 2 1
%SUITE_STARTING% newsimpletest
%SUITE_STARTED%
%TEST_STARTED% testFactorial (newsimpletest)
%TEST_FAILED% time=0 testname=testFactorial (newsimpletest) message=error message sample
%TEST_FINISHED% time=0 testFactorial (newsimpletest)
%SUITE_FINISHED% time=0
CUnit - A Unit testing framework for C - Version 2.1-0
http://cunit.sourceforge.net/
Suite: newcunittest
Test: testFactorial ... passed
--Run Summary: Type Total Ran Passed Failed
suites 1 1 n/a 0
tests 1 1 1 0
asserts 1 1 1 0
make[1]: Leaving directory `/home/tester/NetBeansProjects/CppApplication_1'
</pre>
</li>
</ol>
<h2>Adding Support for Other Test Frameworks</h2>
<p>You can add support for your favorite C/C++ test framework by creating a NetBeans module.
See the NetBeans developer's
<a href="http://wiki.netbeans.org/CND69UnitTestsPluginTutotial"
target="_blank">C/C++ Unit Test Plugin Tutorial</a> on the NetBeans wiki. </p>
<div class="feedback-box"><a href="mailto:users@cnd.netbeans.org?subject=Feedback:%20Adding%20Unit%20Tests%20to%20a%20C/C++%20Project%20-%20NetBeans%20IDE%206.9%20Tutorial">Send Feedback on This Tutorial</a></div>
<br style="clear: both;">
</body></html>