Groups | Search | Server Info | Login | Register


Groups > comp.arch.embedded > #32214

Re: Unit Testing: from theory to real case

From Dave Nadler <drn@nadler.com>
Newsgroups comp.arch.embedded
Subject Re: Unit Testing: from theory to real case
Date 2024-09-01 14:30 -0400
Organization A noiseless patient Spider
Message-ID <vb2bs1$1j3u7$1@dont-email.me> (permalink)
References <vakb55$2sp38$2@dont-email.me>

Show all headers | View raw


On 8/27/2024 6:52 AM, pozz wrote:
 > ...I'm a newbie in this aspect of software development.
 >
 > I know the importance of testing, but we have to admit that it
 > increases the cost of software development a lot, at least at the
 > beginning. Not always we have the possibility to invest this price.

That is backwards. Unit testing, done appropriately, REDUCES the time 
and cost to market. You do need to create sensible and appropriately 
focused tests. You might find this helpful:
https://nadler.com/papers/ESC-111paper_Nadler_corrected.pdf

On 8/27/2024 6:52 AM, pozz wrote:
> I read a lot about unit testing, but unfortunately I usually work on 
> single-developer projects with stressing time constraints, so I never 
> created full tests for an entire project in the past. This means I'm a 
> newbie in this aspect of software development.
> 
> I know the importance of testing, but we have to admit that it increases 
> the cost of software development a lot, at least at the beginning. Not 
> always we have the possibility to invest this price.
> 
> Everytime I start writing some tests, I eventually think I'm wasting my 
> precious time. Most probably because I'm not able to create valid tests.
> 
> So I'm asking you to help on a real case.
> 
> First of all, I have a great confusion in my mind about the subtle 
> differences about mocks, stubs, fakes, dummies and so on. Anyway I think 
> these names are not so important, so go on.
> 
> These days I'm working on a calendar scheduler module. The client of 
> this module can configure up to N events that could be:
> - single (one shot)
> - weekly (for example, on Monday and Saturday of every weeks)
> - monthly (for example, the days 3-5-15 of every months)
> - yearly (for example, the day 7 of months Jan, Feb and Mar)
> Weekly, monthly and yearly events have a starting time and *could* have 
> a maximum number of repetitions (or they could be forever).
> 
> The interface is very simple. I have some functions to initialize the 
> configuration of an event (a simple C struct):
> 
> void calev_config_init_single(CalendarEventConfig *config, time_t 
> timestamp, CalendarEventActions *actions);
> void calev_config_init_weekly(CalendarEventConfig *config, time_t 
> timestamp, uint8_t weekdays, unsigned int nrep, CalendarEventActions 
> *actions);
> void calev_config_init_monthly(CalendarEventConfig *config, time_t 
> timestamp, uint32_t mdays, unsigned int nrep, CalendarEventActions 
> *actions);
> void calev_config_init_yearly(CalendarEventConfig *config, time_t 
> timestamp, uint16_t months, unsigned int nrep, CalendarEventActions 
> *actions);
> 
> I have a function that initializes the module with some pre-programmed 
> events:
> 
>    void calendar_init(CalendarEventConfig *list_events, size_t num_events);
> 
> I have a function that is called every second that triggers actions on 
> occurrences:
> 
>    void calendar_task(void);
> 
> So, the client of calendar module usually does the following:
> 
>    CalendarEventConfig events[4];
>    calev_config_init_...(&events[0], ...
>    calev_config_init_...(&events[1], ...
>    calev_config_init_...(&events[2], ...
>    calev_config_init_...(&events[3], ...
>    calendar_init(events, 4);
>    while(1) {
>      calendar_task();  // every second
>      ...
>    }
> 
> The calendar module depends on some other modules. First of all, it asks 
> for the current time as time_t. It calls make_actions() function, with 
> certain parameters, when an event occurrence expired.
> 
> I know how to fake the time, replacing the system time with a fake time. 
> And I know how to create a mock to check make_actions() calls and 
> parameters.
> 
> Now the problem is... which tests to write?
> 
> I started writing some tests, but after completed 30 of them, I'm 
> thinking my work is not valid.
> 
> I was tempted to write tests in this way:
> 
> TEST(TestCalendar, OneWeeklyEvent_InfiniteRepetition)
> {
>    CalendarEventConfig cfg;
>    calev_config_init_weekly(&cfg, parse_time("01/01/2024 10:00:00"),
>       MONDAY | SATURDAY, 0, &actions);
> 
>    set_time(parse_time("01/01/2024 00:00:00"));  // It's monday
>    calendar_init(&cfg, 1);
> 
>    set_time(parse_time("01/01/2024 10:00:00"));  // First occurrence
>    mock().expectOneCall("make_actions")...
>    calendar_task();
> 
>    set_time(parse_time("06/01/2024 10:00:00"));  // It's saturday
>    mock().expectOneCall("make_actions")...
>    calendar_task();
> 
>    set_time(parse_time("08/01/2024 10:00:00"));  // It's monday again
>    mock().expectOneCall("make_actions")...
>    calendar_task();
> 
>    mock().checkExpectations();
> }
> 
> However it seems there are many sub-tests inside 
> OneWeeklyEvent_InfiniteRepetition test (the first occurrence, the second 
> and third).
> The tests should have a single assertion and should test a very specific 
> behaviour. So I split this test in:
> 
> TEST(TestCalendar, OneWeeklyEventInfiniteRepetition_FirstOccurrence)
> TEST(TestCalendar, OneWeeklyEventInfiniteRepetition_SecondOccurrence)
> TEST(TestCalendar, OneWeeklyEventInfiniteRepetition_ThirsOccurrence)
> What else? When to stop?
> 
> Now for the weekly event with only 5 repetitions.
> TEST(TestCalendar, OneWeeklyEvent5Repetitions_FirstOccurrence)
> TEST(TestCalendar, OneWeeklyEvent5Repetition_SecondOccurrence)
> TEST(TestCalendar, OneWeeklyEvent5Repetition_SixthOccurrence_NoActions)
> 
> The combinations and possibilities are very high. calendar_init() can be 
> called with only 1 event, with 2 events and so on. And the behaviour for 
> these cases must be tested, because it should behaves well with 1 event, 
> but not with 4 events.
> 
> The events can be passed to calendar_init() in a random (not 
> cronologically) order. I should test this behaviour too.
> 
> There could be one-shot, weekly with infinite repetitions, weekly with a 
> few repetitions, monthly... yearly, with certain days in common...
> 
> calendar_init() can be called when the current time is over the starting 
> timestamp of all events. In some cases, there could be future 
> occurrences yet (infinite repetitions) and in others that event can be 
> completely expired (limited repetitions).
> 
> I'm confused. How to scientifically approach this testing problem? How 
> to avoid the proliferation of tests? Which tests are really important 
> and how to write them?
> 
> 

Back to comp.arch.embedded | Previous | NextPrevious in thread | Find similar


Thread

Unit Testing: from theory to real case pozz <pozzugno@gmail.com> - 2024-08-27 12:52 +0200
  Re: Unit Testing: from theory to real case Don Y <blockedofcourse@foo.invalid> - 2024-08-29 13:56 -0700
    Re: Unit Testing: from theory to real case pozz <pozzugno@gmail.com> - 2024-08-30 10:18 +0200
      Re: Unit Testing: from theory to real case pozz <pozzugno@gmail.com> - 2024-08-30 10:37 +0200
      Re: Unit Testing: from theory to real case Don Y <blockedofcourse@foo.invalid> - 2024-08-30 05:21 -0700
        Re: Unit Testing: from theory to real case pozz <pozzugno@gmail.com> - 2024-08-30 18:00 +0200
          Re: Unit Testing: from theory to real case Don Y <blockedofcourse@foo.invalid> - 2024-08-30 12:33 -0700
  Re: Unit Testing: from theory to real case Stefan Reuther <stefan.news@arcor.de> - 2024-08-30 18:23 +0200
  Re: Unit Testing: from theory to real case Dave Nadler <drn@nadler.com> - 2024-09-01 14:30 -0400

csiph-web