Thursday, 5 July 2012

Eclipse Juno has landed with unit testing support for C++

Hi, today I'd like to share a wonderful news with you - a C++ IDE - eclipse CDT version 8.1 (the one included in eclipse Juno that has just landed few days ago) finally includes support for unit testing (which, by the way, JDT had for ages, but nevermind)!

EDIT: It looks like Unit Testing support is not in the default package of eclipse C++ IDE and you have to install it separately from the eclipse update site. See comments.

The good news

CDT 8.1 unit testing supports the following frameworks:

  1. Boost Test Runner
  2. Google Test Runner
  3. Qt Tests Runner

A quick screenshot:

First, you have to enable C++ Unit Testing view:

The main screen of the feature should be shown:

Note that I highlighted one of the buttons in red. This button is "one click run" - it builds the project and runs all the tests - something I've been missing for a long time in C++ world.

Let's give it a try

Now, let's go through a quick tutorial on how to use the feature. I'm going to use Google Test as my unit testing framework and HippoMocks as my mocking framework, so if you don't know at least one of these, it's a good opportunity to learn a bit about them (by observation, since I'm not going to explain today how they work). Also, I'll use C++11 compiler, mainly for the auto keyword. Ok, let's go! For this example, I used:

  1. Ubuntu GNU/Linux
  2. gcc in version at least 4.6 (on Ubuntu you can just install build-essentials package)
  3. google test framework installed (note that on Ubuntu you have to rebuild it from source!)
  4. The latest version of Hippo Mocks framework

Set up a new project

Just create a new C++ empty project and add a new source file. Add the following flag to the gcc compiler: -std=c++0x (it will let you use C++11 features) and the following libraries to the linker:

  1. gtest_main
  2. gtest
  3. pthread

Write the code

We'll use the classic example of copying a file from source to destination. Just paste the following code inside the main file (note that there's no main() function - this is deliberate, as gtest_main.a linked library will provide one for us. Also note that the code shown below isn't good style C++ in terms of header-source separation and namespace using - let's leave it for now, ok? ;-)).

#include <gtest/gtest.h>
#include "hippomocks.h"
using namespace std;

class File
{
};

class Source
{
public:
  virtual File* getData() = 0;
};

class Destination
{
public:
  virtual void write(File* data) = 0;
};

class CopyOperation
{
public:
  void Perform(
    Source* source,
    Destination* destination)
  {
    destination->write(source->getData());
  }
};

TEST(CopyOperationSpecification,
    ShouldCopyFileFromSourceToDestination)
{
  MockRepository mocks;
  auto source = mocks.InterfaceMock<Source>();
  auto destination = mocks.InterfaceMock<Destination>();
  auto file = mocks.Mock<File>();
  CopyOperation copy;

  mocks.ExpectCall(source, Source::getData).Return(file);
  mocks.ExpectCall(destination, Destination::write).With(file);

  copy.Perform(source, destination);
}

Create new run configuration and execute it

Running this example in CDT unit test runner requires you to create a new Run Configuration. Just right-click on the project, select Run As->Run Configurations and double click C++ Unit. On the C/C++ Testing tab, select Google Test Runner from the dropdown list and click Run. If everything goes well, you should see the following screen:

Summary

The unit test runner is a feature I was waiting for a long time and I'm glad to have it, with support for three popular unit testing frameworks. Good job, CDT developers!

That's it. In my next post, I'll be going back to C# and dealing with constructor parameter maintenance. Stay tuned!

11 comments:

Maxx said...

Hi Grzegorz,

I'm a little new with Eclipse (but not with C++) and I really liked what I saw from this Test Runner. Nevertheless, I can't make it work, it doesn't even shows as an installed plug-in.

I've just downloaded Eclipse IDE for C/C++ Developers from "http://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/junor". Am I missing something? Maybe I must download Eclipse complete version.

Currently I'm running Ubuntu 10.04 Lucid Lynx (work place limitations) and I would like to install Eclipse via apt or Synaptic.

Thanks in advance!

Grzegorz Gałęzowski said...

Hi, Maxx,

I just looked at my set of installed plugins and Unit Testing support appears as:

C/C++ Unit Testing Support | 7.0.0.201206111645 | org.eclipse.cdt.testsrunner.feature.feature.group | Eclipse CDT

I found this by going to Help->About Eclipse SDK->Installation Details.

You may have to install this plugin yourself by going to Help->Install New Software and looking there.

I wasn't aware that it's not by default in eclipse C++ IDE. I installed the eclipse classic and downloaded the C++ support after.

nevgeniev said...

could you be a bit more specific WHAT to download from market place?? as there is no "unit testing support" plugin on marketplcace

Grzegorz Gałęzowski said...

Hi, nevgeniev.

I'm not sure whether you can install the plugin from eclipse marketplace.

As you probably know, eclipse has _two_ mechanisms for installing plugins.

Try going to Help->Install New Software-> choose "--All Available Sites--" in the "Work With:" box-> pick "Programming Languages" category and there you should see something like "C/C++ Unit Testing Support"

Unknown said...

Hello Grzegorz,

I hope you can help me dealing with my problem.

I am looking for the test execution logs generated by the cdt-tests-runner (whether the code is unit-tested with boost or Gtest). Can you please, tell me where I can find the logs, I mean the location?

Or is there some way that I can save those test-runs or export them somehow to some location on my local drive?

I am able to unit-test my code and see the test execution in the C/C++Unit console but I'm not much interested in that.

I am using Eclipse Kepler 4.0 and have installed CDT 8.2 plugin for that for the purpose of C++.

--Iflaah

Grzegorz Gałęzowski said...

Hi, Iflaah,

As far as I know, the plugin itself does not produce any useful report. Sure, there are build reports and run reports (you can get those e.g. by launching the CDT test runner, then going to the project directory on disk and searching for files modified less than a minute ago), but I could not find any interesting information there.

On the other hand, if you're interested in gtest logs from the eclipse run, this is easy to do. Just go to the run configuration and on the Arguments tab of your unit test run configuration add the following:

--gtest_output=xml:report.xml

This will make the goole test runner that's triggered from eclipse save XML report in the passed path.

Unknown said...

Hello Grzegorz,

Can you, please, tell me that if the same can work with boost?

I am making tries to make it work with gtest but unfortunately my cdt-test-runner is unable to locate "gtest/gtest.h".

--Iflaah

Grzegorz Gałęzowski said...

Iflaah,

I think so. Under the hood, CDT unit test runner uses console test runners to do the job, so whatever you put into the Arguments tab goes directly as a parameter to the console runner.

So as long as console runner supports saving report file, you can use this way to obtain the report.

I don't know boost test much, but I found an example commanline arguments set that could produce a report.

Unknown said...

Hello Grzegorz,

Firstly, thank you very much for your continuous support.

I'll try the same argument to run with boost again.
I made attempts to make googletest work, following the same way as have mentioned in your page.

So, I somehow made to resolve the inclusion problem of gtest/gtest.h.
Now, when I build the project, there are multiple compile-time errors which point to multiple LOCs of gtest.h for file handlers.

I'll surely check the example that you have suggested now. By the way I am working on Windows platform.

--Iflaah

Unknown said...

Hello Grzegorz,

Thank you very much, I finally achieved what I wanted to; gtest report.

Iflaah

Grzegorz Gałęzowski said...

Iflaah, that's great to hear! :-)