0

let's suppose I have a c source file (source file under test) with content:

uint8 reg1 = I2CRead(20)
uint8 reg2 = I2CRead(24)
uint8 reg3 = I2CRead(28)

if (reg1 != 0x10) || (reg2 != 0x11) || (reg3 != 0x12)
{
   register content wrong ...
} 

else
{
   register content is OK...
}

The I2CRead() function is constructed as follow:

uint8 I2CRead (uint8 address)
{
   I2C_Hw_Istance()->DTR = address  //DTR = Data Transmit Register

   return I2C_Hw_Instance()-> DRR   //DRR = Data Receive Register 
}

Now I'm trying to write a Unit Test (using cpputest framework) where I would like to "fake" the values read back by the function I2CRead() so that all equality expressions within the if() are fulfilled.

The Unit Test file is isolated from the "source file under test" but I can access on a special way the following function within the source file under test: I2C_Hw_Instance().

Using this function I can "fake" my register values within the Unit Test file on a way like this:

I2C_Hw_Istance()->DTR = 20;
I2C_Hw_Istance()->DRR = 0x10;

Because I have 3 I2CRead() function called successively I need to fake the DTR and DRR by each I2CRead() call individually. So this means the Unit test file needs to know when the next I2CRead() function is called to be able to manipulate the values in DTR and DRR.

How to do this in general, any idea?

My Idea was to have a kind of a fake file which is build together with the unit test (just "conceptual"):

FakeFile.c

void fakeRegisters()
{
   if first call of I2CRead() than:
     I2C_Hw_Istance()->DTR = 20;
     I2C_Hw_Istance()->DRR = 0x10;

   if second call of I2CRead()than:
     I2C_Hw_Istance()->DTR = 24;
     I2C_Hw_Istance()->DRR = 0x11;

   if tird call of I2CRead() than:
      I2C_Hw_Istance()->DTR = 28;
      I2C_Hw_Istance()->DRR = 0x12;
}
8
  • 1
    That's called mocking and there are many ways to accomplish what you want. Please do some searches for mock or mocking in relation to unit testing and you should be able to get links to both tutorials, examples and frameworks to help you. Commented Mar 9, 2017 at 13:56
  • Does I2CRead reside in the same source file as the function being tested or in a different file? Commented Mar 9, 2017 at 13:57
  • @dbush : It's in the same file Commented Mar 9, 2017 at 13:59
  • 1
    Please note that testing an I2C driver without any real I2C hardware is a complete nonsense test. Commented Mar 9, 2017 at 14:00
  • @Lundin : That's clear. The idea here is just to test that an special function is called if wrong or right values are read by I2C. It's an "expected" function call test. Commented Mar 9, 2017 at 14:03

1 Answer 1

1

You need a choice of implementations of I2CRead():

uint8_t I2CRead_i2c(uint8_t address)
{
   I2C_Hw_Istance()->DTR = address  //DTR = Data Transmit Register
   return I2C_Hw_Instance()-> DRR   //DRR = Data Receive Register
}


uint8_t I2CRead_fake(uint8_t address)
{
    switch (address) {
    case 20: return 0x10;
    case 24: return 0x11;
    case 28: return 0x12;
    }
    fail_test();                /* however you do this in your xUnit */
}

Now, in your code, you normally use the "real" implementation:

uint8 (*I2CRead)(uint8) = I2CRead_i2c;

When you run your tests, you need to inject your mock implementation:

I2CRead = I2CRead_fake;

This is one of the simplest fake implementations; there's a whole spectrum of fakery available to you if you need it (you might want to have an array containing your register contents so that you can test both the success and failure paths for starters).

Sign up to request clarification or add additional context in comments.

3 Comments

This means it's legal in my Unit Test, when it's time to call the real I2CRead_i2c(), instead this to redirect the call to the I2CRead_fake() ?
Sorry, I couldn't understand that question. Your test will have that last line (I2CRead = I2CRead_fake;), but you do that only in your test, and not your main production code. It's called Dependency Injection, and that's a good search term to read up on. HTH.
Ok, sorry but I'm a beginner in this area and therefore maybe my question was not clear. My understanding regarding Unit Testing up to now was that if I have to test a function within an "source file under test", than the unit test should really call the "real" function and not redirect to a "fake" function. Fakes are allowed only on functions which are external within the source file under test. But yes, I have to read more about it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.