 {
     pinMode(LED_PASS, OUTPUT);
     pinMode(LED_FAIL, OUTPUT);
+}
+
+template<class SerialClass>
+void setupTester(MidiTester<SerialClass>& inTester)
+{
+    inTester.registerTest(new midi::TestFixture("Note On", midi::testNoteOn));
+}
+
+// -----------------------------------------------------------------------------
+
+void setProgressBar(unsigned inProgress, unsigned inTotal)
+{
+    const byte numCols = 16;
+    const byte numPix = 5;
+    const unsigned progress = (inProgress * numCols* numPix) / inTotal;
+    const byte cursorX = progress / numPix;
+    const byte charIndex = progress % numPix;
+    
+    lcd.setCursor(cursorX, 1);
+    lcd.write(charIndex);
+}
+
+// -----------------------------------------------------------------------------
+
+inline void blinkLed(byte inLedNum)
+{
+    digitalWrite(inLedNum, HIGH);
+    delay(100);
+    digitalWrite(inLedNum, LOW);
+}
+
+inline void blinkPass()
+{
+    blinkLed(LED_PASS);
+}
+
+inline void blinkFail()
+{
+    blinkLed(LED_FAIL);
+}
+
+inline void setLedsFinal(bool inSuccess)
+{
+    if (inSuccess)
+    {
+        digitalWrite(LED_PASS, HIGH);
+        digitalWrite(LED_FAIL, LOW);
+    }   
+    else
+    {
+        digitalWrite(LED_FAIL, HIGH);
+        digitalWrite(LED_PASS, LOW);
+    }
 }
 
 // -----------------------------------------------------------------------------

    setupMidiInstance<SoftwareSerial>(midiSW);
    setupLCD();
    setupLEDs();
}

// -----------------------------------------------------------------------------

void loop()
{
    
}


// -----------------------------------------------------------------------------

BEGIN_MIDI_NAMESPACE

class TestFixture
{
public:
    typedef const char* String;
    typedef bool (*Functor) (void);
    
public:
    TestFixture(String inTestName, 
                Functor inFunctor)
        : mTestName(inTestName)
        , mFunctor(inFunctor)
    {
    }
    
public:
    inline bool operator() (void)
    {
        return mFunctor();
    }
    
    inline String getName() const
    {
        return mTestName;
    }
    
private:
    String mTestName;
    Functor mFunctor;
};

// -----------------------------------------------------------------------------

template<class SerialPort>
class MidiTester
{
public:
    explicit MidiTester(MidiInterface<SerialPort>& inInstance)
        : mInstance(inInstance)
    {
    }
    
    virtual ~MidiTester()
    {
    }
    
public:
    inline bool performTestFixture(TestFixture* inFixture)
    {
        if (inFixture != 0)
        {
            return (*inFixture)();
        }
        return false;
    }
    
    inline bool expect(bool inCondition) const
    {
        if (inCondition == false)
            blinkFail();
        else
            blinkPass();
        return inCondition;
    }
    
public:
    inline void registerTest(TestFixture* inFixture)
    {
        mTests[mNumActiveTests++] = inFixture;
    }
    
    bool runTests()
    {
        for (unsigned i = 0; i < mNumActiveTests; ++i)
        {
            if (mTests[i] != 0)
            {
                if (expect(performTestFixture(mTests[i]) == false))
                {
                    // \todo Display message
                    // \todo Store error number and continue.
                    return false;
                }
            }
            setProgressBar(i, mNumActiveTests);
        }
        return true;
    }
    
private:
    MidiInterface<SerialPort>& mInstance;
    TestFixture* mTests[NUM_TESTS];
    unsigned mNumActiveTests;
};

// -----------------------------------------------------------------------------

bool testNoteOn()
{
    return true;
}

// -----------------------------------------------------------------------------

END_MIDI_NAMESPACE

midi::MidiTester<HardwareSerial> testerHW(midiHW);
midi::MidiTester<SoftwareSerial> testerSW(midiSW);

// -----------------------------------------------------------------------------

template<class SerialClass>
void setupMidiInstance(midi::MidiInterface<SerialClass>& inInstance)
{
