Fwd: [googlemock: 1645] Best Practices for testing a sequence of operations

657 views
Skip to first unread message

Patrick Doyle

unread,
Oct 18, 2012, 1:14:46 PM10/18/12
to googl...@googlegroups.com
Hello Moderator,
Could you please approve my message from last week (or give me
guidance on how I should reframe my question). I don't see it listed
in the archives for GoogleMock.

Thank you.

--wpd



---------- Forwarded message ----------
From: wpd <wpd...@gmail.com>
Date: Thu, Oct 11, 2012 at 4:34 PM
Subject: [googlemock: 1645] Best Practices for testing a sequence of operations
To: googl...@googlegroups.com


Hello All,
I have constructed a Google Mock application to test that a specific
sequence of operations is performed in order. (I did this because I
am rewriting an existing body of C code in C++ and decided I wanted to
create unit tests for the new code as I went along).

Following the existing body of code, I created an interface class
(that calls the underlying library functions), mocked that class, and
now have a unit test that looks something like this:
{ InSequence s;
EXPECT_CALL(libhsi, hsi_open(0));
EXPECT_CALL(libhsi, hsi_isp_start(port, 115200)).Times(AtLeast(1));

// micro_to_isp_mode()
EXPECT_CALL(libhsi, hsi_spi_write_bits(HSI_FPGA_PORT_REG(CONTROL, port),

HSI_FPGA_UART_CONTROL_POWER_ENABLE, 0));
// How do I model the fact that we need to sleep 100ms (ish) in order to
// "Give the power time to stabilize off"?
EXPECT_CALL(libhsi, sleep_ms(Ge(100)));
EXPECT_CALL(libhsi, hsi_spi_write_bits(HSI_FPGA_PORT_REG(CONTROL, port),

HSI_FPGA_UART_CONTROL_FORCE_CLOCK_LOW, 0));

EXPECT_CALL(libhsi, hsi_spi_write_bits(HSI_FPGA_PORT_REG(CONTROL, port),

HSI_FPGA_UART_CONTROL_POWER_ENABLE, 1));
EXPECT_CALL(libhsi, sleep_ms(Ge(1000)));
// How do I model the fact that we need to wait 1000ms after this?

// flush_rxbuf()
EXPECT_CALL(libhsi, hsi_isp_recv(_, _, 0));

EXPECT_CALL(libhsi, isp_synchronize(mcuclock, 0));

EXPECT_CALL(libhsi, isp_disable_echo());

EXPECT_CALL(libhsi, isp_read_part_id());

EXPECT_CALL(libhsi, isp_read_boot_code_version(_, _));

EXPECT_CALL(libhsi, isp_unlock());

EXPECT_CALL(libhsi, isp_prepare_sectors(0, _));

EXPECT_CALL(libhsi, isp_erase_sectors(0, _));

EXPECT_CALL(libhsi, isp_blank_check_sectors(1, _)).WillOnce(Return(0));


EXPECT_CALL(libhsi, isp_write_to_ram(LPC17XX_RAM_ADDR, _, _));

EXPECT_CALL(libhsi, isp_prepare_sectors(_, _));

EXPECT_CALL(libhsi, isp_copy_ram_to_flash(_, LPC17XX_RAM_ADDR, _));


EXPECT_CALL(libhsi, isp_write_to_ram(LPC17XX_RAM_ADDR, _, _));

EXPECT_CALL(libhsi, isp_prepare_sectors(_, _));

EXPECT_CALL(libhsi, isp_copy_ram_to_flash(_, LPC17XX_RAM_ADDR, _));


EXPECT_CALL(libhsi, hsi_isp_stop());
}
ASSERT_TRUE(mdp.downloadMotorCode(0, codeblock, sizeof(codeblock)));


This is the "Everything worked right" case. Now I would like to start
testing some of the failure cases, such as would happen when one or
more of these function calls returns a non-zero value.

What is the best practice for doing something like this? Ideally, I
would like to implement a dozen or two unit tests in which I
successfully navigate the sequence up to some point, (for example, up
to the call to 'isp_synchronize()'), have that point return a failure
code, and have my unit test demonstrate that it handled the failure
properly. Lather, rinse, and repeat for the next call in sequence
('isp_disable_echo()', 'isp_read_part_id()', etc...). It would be
awfully nice if I didn't have to repeat myself all dozen or two times.

Thank you for any tips you might have to offer...

--wpd

Vlad Losev

unread,
Oct 19, 2012, 12:32:04 PM10/19/12
to Google C++ Mocking Framework
Not sure about others, but I did receive your original message forwarded from the list. It missing from the UI display is probably a bug.

As for the question, I am not sure how you can shortcut it. If you want to verify N control flows, you have to write N tests. You can simplify your code a bit by setting up default behavior of your mock to match the success case and then overriding each call to return a failure:

class HsiTest : public Test {
 protected: 
  virtual void SetUp() {
    ON_CALL(libhsi, hsi_open(_)).WillByDefault(Return(true));
    ON_CALL(libhsi, hsi_isp_start(port, 115200)).WillByDefault(Return(true));

  
};

Then in each test you set expectation on the mock method that you want to fail:

TEST_F(HsiTest, IspStartFails) {
  EXPECT_CALL(libhsi, hsi_is_open(0)).WillOnce(Return(false));
  // Ensure that the following call is not made.
  EXPECT_CALL(libhsi, hsi_isp_start(port, 115200)).Times(0);
  // Further checks to verify the behavior of downloadMotorCode.
}

This allows you to write a short test for each failure condition. Note that you cannot assert call order this way, but you can do that in a test that verifies the success case.

Patrick Doyle

unread,
Oct 19, 2012, 1:22:26 PM10/19/12
to Vlad Losev, Google C++ Mocking Framework
Thanks. That's an approach that I hadn't considered. I'll give that a try.

--wpd
Reply all
Reply to author
Forward
0 new messages