Search code examples
c++sdlgoogletest

How to test a program using SDL without a graphical interface?


I made a C++ program that uses SDL for display and sound. I am implementing gtest to test the graphical functions, for example to draw a pixel :

void Interface::draw_pixel(unsigned short x, unsigned short y, bool on) {
  if (on) {
    SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
  } else {
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
  }
  SDL_Rect rect = {normalize_x(x), normalize_y(y), SIZE_MULTIPLIER_, SIZE_MULTIPLIER_};
  SDL_RenderFillRect(renderer, &rect);
}

And to check if this pixel is indeed drawn :

bool Interface::is_pixel_on(int x, int y) {
  p_ = (uint8_t *) SDL_GetWindowSurface(window)->pixels + normalize_y(y) * SDL_GetWindowSurface(window)->pitch +
       normalize_x(x) * bpp_;
  SDL_GetRGB(*(uint32_t *) p_, SDL_GetWindowSurface(window)->format, &rgb_.r, &rgb_.g, &rgb_.b);
  return rgb_.r != 0;
}

I would like to draw a pixel and check if it is drawn in C.I. tests. I have tried to create the SDL window with the SDL_WINDOW_HIDDEN flag but it doesn't draw and my test fail.

Do you have any idea or hints how it should be done?


Solution

  • Generally, unit tests don't test gui but logics.

    Have a layer of abstraction between library and your logic.

    Eg:

    namespace mygui
    {
        RenderFillRect(MyRenderer renderer, MyRect* rect);
    };
    
    void Interface::draw_pixel(unsigned short x, unsigned short y, bool on) {
      if (on) {
        MySetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
      } else {
        MySetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
      }
      MyRect rect = {normalize_x(x), normalize_y(y), SIZE_MULTIPLIER_, SIZE_MULTIPLIER_};
      MyRenderFillRect(renderer, &rect);
    }
    

    Mock mygui::RenderFillRect and check if it's called with correct arguments after calling Interface::draw_pixel.


    After your elaborated in comment about testing for CHIP8 interpreter, my suggestion is still relevant.

    I'll suggest you to mock SDL function calls by using the instruction here.

    Another way is mocking Interface::draw_pixel() to make sure one instruction is writing to the correct position.

    I'm not sure when do you need to test SDL library. The only scenario I came up with is that it might breaks when you upgrade the library version. However most of time it doesn't get upgraded frequently.