Friday, August 14, 2009

Debugging the C++ Preprocessor

I don't want to start a discussion about the good and the bad of the good old c preprocessor macros. Today a macro helped me keeping the DRY principle. I found myself repeatingly writing the following three lines:
int GetValue() const {return this->value_;}
void SetValue(const int& value) {this->value_ = value;}
__declspec(property(get = GetValue, put = SetValue)) int Value;
So why not make a makro:
#define DECLARE_PROPERTY(Type,Name,Member) \
Type Get##Name() const {return Member;} \
void Set##Name(const Type##& value) {Member = value;} \
__declspec(property(get = Get##Name, put = Set##Name)) Type Name;
The definiton would look like this:
DECLARE_PROPERTY(int, Value, this->value_)
Because I'm not writing macros too often (and this should be the case in future, too) I needed to review the preprocessor output. Here are the steps: Enable the following options for the cpp file you want to debug and compile the unit or module:
The result will be a a file with the extension .i in the source directory which contains the preprocessor expanded file. This file can be very large so it is a good idea to put a unique comment marker before (and/or after) the definition to find the result easier.
ps.: One advantage of C++/CLI is that you still have the power of the c preprocessor which I'm sometimes (not too often) missing in C#. Okay, you can kick on T4 templates but that's a different story and it's questionable if this doesn't violate the KISS principle.

Thursday, August 13, 2009

Running Notepad++ under Wine

Notepad++ is a great Editor which unfortunately is just compiled for windows.
But it runs nicely under Wine:

ps.:
So far I was a big fan of Live Writer. Now, searching for an alternative on Linux (Drivel didn't do the job), I discovered that I can write my posts with Google Docs.
This is the first post I've written and published with Google Docs.



SyntaxHighlighter does the better job

I was using Code Snippet plugin for Windows Live Writer with poor resutls. Thanks to this instructions now I'm using SyntaxHighlighter with much better results and I reworked the C++/CLI unit testing post to make use of SyntaxHighlighter.

How MbUnit helps not violating DRY

When I was on a .NET user group meeting in Karlsruhe about TDD the speaker (speaking nicest bavarian dialect) created a unit test and did the unbelievable: He marked the 15 lines of code that made up the first test pressed <CTRL>+<C>, moved some lines below and pressed <CTRL>+<V> and changed some values of the test.

The audience was uhhing! Several of the listeners were wearing the CCD arm ring and could not tolerate a violation of the DRY principle.

Indeed Unit Test code must be written and maintained with the same care as production code.

MbUnit supports a very neat feature that helps keeping the DRY principle: [RowTest]

Instead of writing many TestEquals derivates you simply call the function multiple times with the Row attribute...

[RowTest]
[Row("03000000010000000000110101000063","","03000000010000001100110101000023","", false)]
[Row("03000000010000000000110101000063","","03000000010000000000110101000063","", true)]
[Row("03000000010000000000110101000063","name","03000000010000000000110101000063","", false)]
[Row("03000000010000000000110101000063","","03000000010000000000110101000063","name", false)]
[Row("03000000010000000000110101000063","name","03000000010000000000110101000063","name", true)]
[Row("03000000010000000000110101000063","name","03000000010000001100110101000023","name", false)]
void BarcodePatternTest::TestEquals(String^ barcode1, String^ realName1, String^ barcode2,  String^ realName2, bool isEqual)
{
 CBarcodePattern patternA((LPCTSTR)CString(barcode1),(LPCTSTR)CString(realName1));
 CBarcodePattern patternB((LPCTSTR)CString(barcode2),(LPCTSTR)CString(realName2));

 Assert::AreEqual(isEqual, CBarcodePattern::Equals(patternA,patternB));
 Assert::AreEqual(isEqual, (patternA == patternB));
 Assert::AreEqual(isEqual, (patternA.Equals(&patternB)));
}

Tuesday, August 11, 2009

Refactorings in Agile Development

In Agile Software Development Refactoring starts with the first lines of code you write. Jeremy Miller discusses in this excellent article published in the MSDN magazine why this makes sense and can help you deliver products that meet your customer expectations in time.

As most practices in software development Refactoring is not an art but a science.

I recommend Refactoring to patterns by Joshua Kerievsky as a book resource.

The web page www.refactoring.com maintained by well known Martin Fowler contains a brief catalog I regularly use to lookup patterns when doing refactoring work.

Friday, August 7, 2009

Code Snippet plugin for Windows Live Writer

Writing my last blog post I used “Code Snippet plugin for Windows Live Writer” to embed source code.
I had some difficulty with the formatting once posted.
This post suggested to switch off a special BlogSpot setting to convert line feeds. It didn't really work, but when I remove all linefeeds from the html I get it right:
   1: #pragma once
   2:  
   3: namespace MyDiagnosticsNet {
   4:  
   5:   using namespace System;
   6:   using namespace System::Diagnostics;
   7:  
   8:   public ref class MyTraceListener : public TraceListener
   9:   {
  10:   public:
  11:     MyTraceListener();
  12:     virtual void Write(String^ message) override;
  13:     virtual void WriteLine(String^ message) override;
  14:     virtual void TraceEvent(TraceEventCache^ eventCache, String^ source, TraceEventType eventType, int id);
  15:     virtual void TraceEvent(TraceEventCache^ eventCache, String^ source, TraceEventType eventType, int id, String^ message);
  16: )
  17: )  private:
  18:     void CheckedTrace(String^ message);
  19:     static String^ PrependTimeStamp(String^ message);
  20:     MyBaseDescr* GetBaseDescr();
  21:     MyBaseDescr* myBaseDescr_;
  22:   };
  23: }
I think I have to do some more experiments...

Thursday, August 6, 2009

My Approach for Unit testing c++ with Visual Studio 2005

Visual Studio 2008 offers the ability to write unit tests in managed c++ code. In my current project work I have to use Visual Studio 2005 because of external constraints.

In the following article I will describe how…

  • to setup and write unit tests in c++/cli for MbUnti
  • to write the production code in unmanaged c++ with MFC
  • to setup a test project for debugging

Prerequisites

You need to have Visual Studio 2005 and MbUnit installed.

Create a new Unit Test Project

1.) Create a new CLR Class Library.

image

2.) Add a reference to the MbUnit framework you want to use.

image

3.) Add the namespace MbUnit::Framework.

using namespace MbUnit::Framework;

4.) Add the [TestFixture] attribute to the public ref class you want to use as test container.

[TestFixture]    
public ref class HelloUnitTest    
5.) Add a new public method to the test class and mark it with the[Test] attribute.
public:
  [Test]
  void TestHello()
  {

6.) Now the code should look like this:

// MyCppTest.h

#pragma once

namespace MyCppTest {

  using namespace System;    
  using namespace MbUnit::Framework;

  [TestFixture]    
  public ref class HelloUnitTest    
  {    
  public:
    [Test]    
    void TestHello()    
    {        
    }    
  };    
}

7.) Build the project and give it a first run in the MbUnit Gui Runner.

Therefore click on Assemblies->Add Assemblies.. and select the test dll.

image

You can expand the tree and you will see your test fixture and your test method.

image

Now we have the first working version of the unit test. It passes and we’re done! Done? Not quite. Now we need to test the code we are writing to get paid for. Following the rules of TDD we need to test first.

So let’s look into the requirements: The module should return a string that contains “Hello†on request. (Ok, maybe this is not a for a real word product, but you never know…)

8.) Implementing the testing code

I know that the module is used in a MFC environment. So I first need to enable support for that. Switch on 'Use MFC in a Shared DLLâ€

image

Include afxwin.h in StdAfx.h

#include "afxwin.h"
Now write the the test code:
public:    
  [Test]    
  void TestHello()    
  {        
    HelloWorldProvider provider;
    CString response = provider.request();
    Assert::Contains("Hello", response);
  }


first test failure is that we cannot compile, so we need to create the production library.
Implementing the production code

The production library shall be unmanaged. So we go to the solution, click ‘Add new project’ and create a new MFC DLL.

image

Use the standard settings and finish the wizard (If you look into the generated StdAfx.h file we’ll see the what additionally might be added to the StdAfx.h file for the unit test).

Add a new class HelloWorldProvider:

image

image

Implement the request function:

class HelloWorldProvider    
{    
public:    
  HelloWorldProvider(void);
  ~HelloWorldProvider(void);
  CString request() const
  {
  return L"hello world!";
  }
};
Compile the production code and compile the test code. The test code does not compile I changed it to:
// MyCppTest.h
#pragma once

#include "..\HelloWorldProvider\HelloWorldProviderImpl.h"

namespace MyCppTest {
  using namespace System;
  using namespace MbUnit::Framework; 

  [TestFixture]    
  public ref class HelloUnitTest    
  {    
    public:    
      [Test]    
      void TestHello()    
      {        
        HelloWorldProvider provider;    
        CString response = provider.request();
        Assert::Contains("Hello", gcnew String(response));    
      }    
  };    
}

Compile again and I get a linker error:

1>------ Build started: Project: MyCppTest, Configuration: Debug Win32 ------ 1>Compiling... 1>MyCppTest.cpp 1>Linking... 1>MyCppTest.obj : error LNK2028: unresolved token (0A000010) "public: __thiscall HelloWorldProvider::~HelloWorldProvider(void)" (??1HelloWorldProvider@@$$FQAE@XZ) referenced in function "public: void __clrcall MyCppTest::HelloUnitTest::TestHello(void)" (?TestHello@HelloUnitTest@MyCppTest@@$$FQ$AAMXXZ) 1>MyCppTest.obj : error LNK2028: unresolved token (0A000011) "public: __thiscall HelloWorldProvider::HelloWorldProvider(void)" (??0HelloWorldProvider@@$$FQAE@XZ) referenced in function "public: void __clrcall MyCppTest::HelloUnitTest::TestHello(void)" (?TestHello@HelloUnitTest@MyCppTest@@$$FQ$AAMXXZ) 1>MyCppTest.obj : error LNK2019: unresolved external symbol "public: __thiscall HelloWorldProvider::~HelloWorldProvider(void)" (??1HelloWorldProvider@@$$FQAE@XZ) referenced in function "public: void __clrcall MyCppTest::HelloUnitTest::TestHello(void)" (?TestHello@HelloUnitTest@MyCppTest@@$$FQ$AAMXXZ) 1>MyCppTest.obj : error LNK2019: unresolved external symbol "public: __thiscall HelloWorldProvider::HelloWorldProvider(void)" (??0HelloWorldProvider@@$$FQAE@XZ) referenced in function "public: void __clrcall MyCppTest::HelloUnitTest::TestHello(void)" (?TestHello@HelloUnitTest@MyCppTest@@$$FQ$AAMXXZ) 1>c:\temp\MyCppTest\Debug\MyCppTest.dll : fatal error LNK1120: 4 unresolved externals 1>Build log was saved at "file://c:\temp\MyCppTest\MyCppTest\Debug\BuildLog.htm" 1>MyCppTest - 5 error(s), 0 warning(s) ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Now we have the following choices: 1.) If the class is exposed in the dll interface, we can statically link to the production code which is the most accurate solution because you are testing the binary code that get’s shipped. 2.) If the class is not part of the dll interface, we can create a link library with that class and link it to both: the production module and the test module 3.) If the class is not part of the dll interface, we can add the cpp file to the test project that a object file get’s created for it and mark it as unmanaged .

I will now follow the 3rd approach…

Use ‘Add existing …’ to add the HelloWorldProviderImpl.cpp to the project, compile, run the test and …

image

It fails! It complains that the returned string does not contain “Helloâ€. The inspected string is “hello world†which does not comply to our requirements. So let’s correct that and run again: It fails again! A closer look at the MbUnit message reveals the problem:

String “Hello†does not contain “hello worldâ€

The assert must be vice versa. Obviously this is a code comment bug in MbUnit:

image

So let’s correct the order:
Assert::Contains(gcnew String(response),"Hello";
…and the test is GREEN:

image

Setting up for debugging

To debug into the test code simply set up the GUI runner as startup project with the following options:

image

Now you can start the runner by pressing F5…

Finally some useful links

Executing MbUnit GUI and Console from Visual Studio

Unit Testing with MBUnit (An Introduction) typeof Goes to T::typeid for use of [ExpectedException = ArgumentException::typeid] attribute

ps.: sorry for the poor code formatting. I was using first time Code Snippet plugin for Windows Live Writer.