1

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?

genpfault
  • 51,148
  • 11
  • 85
  • 139
TheMackou
  • 123
  • 1
  • 2
  • 11
  • 1
    Separate your logic between gui and calculation. Don't test if library draw the point. Test if your logic put the point to the right position and render. – Louis Go Sep 07 '21 at 09:03
  • 1
    You can do that with offscreen software renderer (don't create window but surface instead, and associate renderer with that surface). However SDL_GetWindowSurface is just wrong here even if window is present. – keltar Sep 07 '21 at 11:30
  • Question is what are you trying to test? Testing UI using unit test (gtest) is usually hard or pointless. – Marek R Sep 07 '21 at 17:04
  • I am making a CHIP8 interpreter, and I want to check that one instruction will indeed print the sprite on the display. Should I have a separated screen memory that SDL would jsut display ? And I can test the value of pixel directly from that memory? Because currently my display memory is within SDL. – TheMackou Sep 07 '21 at 19:59
  • My suggestion is still relevant and I found a source might be [helping](https://stackoverflow.com/a/28392341/4123703). – Louis Go Sep 08 '21 at 01:06

1 Answers1

2

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.

Louis Go
  • 2,213
  • 2
  • 16
  • 29