Unit testing OpenGL applications
Nowadays comprehensive testing is a must for any software product. However, it isn’t such a general rule when it comes to graphics applications. Many developers face difficulties when they have to test their rendering codes. Manual tests and visual feedback is sometimes satisfactory but if one would like to have automated regression tests usual approaches seem to fail. Even if at first sight unit testing of rendering code doesn’t look really straightforward, in fact it is. OpenGL is not an exception from this rule as well. In this article I would like to briefly present a few methods how to unit test OpenGL rendering code and also present my choice and the reasons behind the decision.
There are several ways how to create automated test cases for rendering code. To present the different approaches we first have to select a small portion of our rendering code to demonstrate the differences of each technique, mentioning the strengths and weaknesses of them.
Before going any further, we have to lay down our requirements against a good OpenGL unit testing environment:
- Verifies results – This is the most basic requirement for any testing framework. We have to have the ability to check whether the rendering code executed by the module is valid and works as expected.
- Productive – The usage and maintenance of the framework shall require minimal effort. Many times unit testing is attacked because it requires additional code writing. While this is generally true, a nice unit testing environment can be kept very simple yet flexible. An OpenGL testing environment shouldn’t be different.
- Fast – This is a general requirement for any unit testing environment especially when combined with a continuous integration framework. We want our test results as fast as possible as long feedback cycles severely slow down the development process.
- Standalone – Does not require complex setup or environmental support in order to be executed. This is a general requirement when we deal with unit testing as if the code is tightly coupled by any of the surroundings then both development and maintenance costs increase.
- Compatible – Does not require any special hardware so it can be tested on a machine that wouldn’t necessarily be suitable for manually testing the actual product. This is especially important when the target hardware is some type of embedded platform. It is also important to ensure that it will work on hardware provided by different vendors. In one word, it should comply to the standard, not to driver implementations.
- Cross-platform – Does not rely on the services of a particular operating system or platform, instead it can be executed on any machine as usually all unit tests. Of course, this restriction can be relaxed depending on actual use case scenarios.
Now that we know what we would like to achieve, we can continue with a sample use case. Lets say we would like to create an OpenGL 3.2 based rendering engine. One of the first things that we would write is a class (or set of classes) that will help us handling OpenGL buffer objects as it seems to be one of the main building blocks of such a system. As a very basic example, our first version of the buffer handling class will act simply as a wrapper for buffer objects having the following interface:
class Buffer {
public:
Buffer();
virtual ~Buffer();
};
As it can be seen for now we just require that our class to handle the creation and deletion of a buffer object. Obviously, our test has to check that the constructor successfully creates a buffer by calling glGenBuffers and the destructor deletes that by calling glDeleteBuffers with proper arguments. Now lets see what possibilities we have to test OpenGL rendering code and whether it conforms to our requirements and is able to test our simple module.
Checking rendered image
The most naive solution for creating automated tests for rendering code is to actually execute the OpenGL commands and check whether the rendering happened as expected. This can be done by comparing reference rendering results to the actual ones. This approach has the benefit that we actually verify the concrete behavior but lets see how it looks like when we check against our previously laid down requirements:
- Verifies results – Partially fulfilled. We check against the correct behavior, however, the ability to reproduce the actual same image is often difficult if not impossible due to different relaxations regarding to precision in both the standard and driver implementations. In order to have reproducible results the testing environment shall also provide some mechanisms to allow slight differences.
- Productive – Not met. It can be quite expensive to create an assertion system. Also, the production of reference data can be quite time consuming.
- Fast – Not met. Even if the checkers are highly optimized components of the framework, it wouldn’t fit into the time-frame of unit test cycles to execute possibly thousands of test cases that require complete verification of the produced image.
- Standalone – Not met. We have to setup a complete rendering environment in order to test even the simplest rendering code. Also, it relies on the assumption that the rendering code actually produces some image. As we can see in our buffer handling example, this is not always the case.
- Compatible – Not met. We need a testing machine that has the hardware capabilities to execute the rendering code and produce the required image.
- Cross-platform – Partially fulfilled. If our rendering code is cross-platform then it is possible to test it on any of the supported platforms. However, this makes the assertion system even more complicated as it also has to support the target platforms. Also, driver implementations may vary even further when dealing with different operating systems.
As we can see, even if this version is quite natural way of thinking for anybody it’s simply impractical and not feasible for actual use. To be able to find a good solution we must look deeper into what unit testing exactly is as the presented solution has nothing to do with it. In order to be able to do real unit testing we have to eliminate the dependency on OpenGL driver implementations and strictly concentrating on the module under test.
Fake OpenGL driver
The second presented solution is to create a layer between the code under testing and the actual OpenGL driver implementation. This can be easily achieved by creating a fake driver, as an example a dynamic library called opengl32.dll in case of Windows. This additional layer would do nothing else than just recording and checking whether the required API calls happened as expected. Providing an interface towards the testing environment that can be used to request the informations needed to make a verdict about the successfulness of the test case.
Beside that this version accommodates much more to the idea behind unit testing it also has the benefit that it is acting as a totally independent layer and does not directly disturb the development of the actual code. Still, if we go back to our checklist we have some issues that raise some concerns regarding to the applicability of this approach:
- Verifies results – Partially fulfilled. It is up to the implementation of the new layer whether it provides the required facilities to properly check the behavior of our tested code. Nevertheless, it also highly depends on the implementation on how we define correct behavior and the responsibility of the library.
- Productive – Partially fulfilled. Now we have a separate module that helps us in the testing. This may introduce some additional maintenance work but, of course, this depends on how intelligently is the library actually implemented.
- Fast – Mostly resolved. We do not have expensive assertions, however, as we have a quite restricted interface between our testing environment and the new layer we most probably met situations when we have to make trade-offs between speed and flexibility.
- Standalone – Resolved. We have a totally independent module that is responsible to simulate the surrounding environment of the code under testing as it should be when doing unit test. However, the question arises whether we would like this layer to be that separated from the testing code.
- Compatible – Resolved. There is no dependency on dedicated graphics hardware or any other piece of metal. In case of a robust driver simulation layer we can test our code on whatever platform we prefer.
- Cross-platform – Resolved. As previously mentioned, if the additional layer is well designed, there should be no problems regarding to this issue.
Now we have a resolution that can be seriously taken into consideration as a good way to test rendering code. It can also be simply applied to test our buffer handling code as well. Also, as it is a totally standalone software element it is also very portable so it is easy to reuse between projects written in different programming languages and for different platforms.
Still, there is one thing that may need further investigation. Most probably for the other portions of our production code we already use some kind of mocking mechanisms for our unit testing. Having an additional interface type to handle the OpenGL related mocking (as the presented fake driver approach is nothing more than a mock library for OpenGL) may reduce the productivity of our developers. Also, it can make the testing code less uniform so introducing a slight maintenance penalty. At least for comparison, we should try to integrate the OpenGL mocking into our existing mocking facilities.
API mocks
All the people who seriously do unit testing use some mocking techniques to eliminate dependency on any external software element like databases, network or another code element. Why should the OpenGL API be different?
As I already written about that I use GoogleMock to test my C++ code. Lets see how this mocking framework is capable for removing OpenGL related dependencies. By default, GoogleMock does support only class mocks, however it is fairly straightforward to mock out OpenGL API functions as well. As an example, our buffer handling class needs at least a mock for the glGenBuffers and glDeleteBuffers API functions. These mocks can be very easily created using GoogleMock as part of a class in the following way:
class CGLMock {
public:
MOCK_METHOD2( GenBuffers, void(GLsizei n, GLuint* buffers) );
MOCK_METHOD2( DeleteBuffers, void(GLsizei n, GLuint* buffers) );
};
CGLMock GLMock;
This, however is not enough to replace the already existing real API function pointers with the fake ones. I did this with a nasty little trick by taking advantage of the C preprocessor:
#undef glGenBuffers #define glGenBuffers GLMock.GenBuffers #undef glDeleteBuffers #define glDeleteBuffers GLMock.DeleteBuffers
The #undef is needed because I use GLEW for accessing OpenGL API functions and it uses macros for the API function names as well.
All these are put into a file that can be called like glmock.h. In order to force the production code to use these definitions when trying to access the API inside a test case we have to create a wrapper header called something like opengl.h that will include original headers in case of normal build and include the mock library in case of unit test build. This is kind of a workaround but it works quite well in practice.
In theory, this trick can be applied in case of any mocking framework. As a result, from now we can write a very simple test case to check the creation and deletion of our buffer object as easily as the following few lines of code:
TEST(BufferTest, CreationAndDestruction) {
EXPECT_CALL(GLMock, GenBuffers(1,_))
.WillOnce(SetArgumentPointee<1>(13));
Buffer* buffer = new Buffer;
EXPECT_CALL(GLMock, DeleteBuffers(1,Pointee(13)));
delete buffer;
}
I would not like to go into the details related to the interface of GoogleMock. In one word, the test case above checks whether the constructor calls glGenBuffers with a number of 1 for the requested number of buffer objects and returns a buffer ID in the pointer argument, and at the end it checks if glDeleteBuffers was called with the buffer ID value got at creation.
It is maybe a matter of taste whether the second or this third solution is more attractive for you. My choice was this last solution because I didn’t want to develop an separate library and also was afraid of messing up my test code with different syntactical representations of mocks. Finally, lets sum up the achievements of this last version:
- Verifies results – Fulfilled. An existing mocking framework is used for emulating the OpenGL API thus we have all the facilities required for the proper checking of the API calls.
- Productive – Fulfilled. Again, we don’t have to deal with writing an own mocking mechanisms as we have everything out of the box. We can also incrementally extend our mock library on-the-fly while editing the test cases and the production code.
- Fast – Resolved. Our rendering related unit test cases should be as fast as any other test codes as they are indifferent, just the purposes are dissimilar.
- Standalone – Mostly resolved. The mocking library is independent, however, as we’ve seen, the introduction may require some nasty tricks in order to inject foreign code into the production code.
- Compatible – Resolved. From this point of view, this approach behaves the same as the previous version.
- Cross-platform – Resolved. Again, the same like in the previous case, maybe even a bit easier to make it portable.
Conclusion
We’ve seen a few ways how we can extend our testing environment in order to support the verification of rendering code. We’ve also seen that the range varies from techniques that provide high level methods suitable especially for functional testing, until very low level methods that tightly integrate in the mocking methodology of unit testing. These, of course, do not replace traditional testing methods rather they extend it in order to find problems in the early phases of software development.
I also tried to present a very basic example of production code that needs such a facility in order to be tested, as well as a sample test case written using GoogleMocks applying the last presented technique.
While writing this article I got the idea that it would be nice to have a complete and general framework for OpenGL testing. If there is interest for it, maybe I’ll allocate some time to write one. I’m also interested which approach is the most attractive for you, especially if you have some concrete experience with any of these or with some other technique.
| Print article | This entry was posted by Daniel Rákos on February 22, 2010 at 7:54 pm, and is filed under General, Graphics, Programming. Follow any responses to this post through RSS 2.0. You can leave a response or trackback from your own site. |


about 3 years ago
Are more than OpenGL resource management unit tested? Unless the mock ups actually passes everything to GL, I can’t see how one can check invariants of rendering/gpgpu results?
about 3 years ago
If you write your own fake for the OpenGL API you can do whatever you want like checking whether the sequence of API calls is valid or not.
Anyway, checking the actual rendering results on actual hardware is far beyond the scope of unit testing. As I mentioned, there should be always some kind of functional test and to see whether the rendering works can be easily done with such.
The purpose of unit testing is to identify coding errors in the early phase of the development as if you check rendering code only in functional testing it can become quite a big headache to figure out why you get a black screen or totally invalid rendering. Usually these kind of errors are the results of some typing or other type of error in some of the smallest modules of the code.
At functional test level you have a much bigger code base and it is more difficult to find the module responsible for the incorrect behavior. If you at least check your code against the design and specification documents with unit tests, you can be more sure than an error found during functional test is related to integration rather than a problem with an individual module.
Beside that, unit tests are quite cheap and it is easy to have a fast feedback regression set so you get immediate notice about whether a new functionality made wrong a legacy one. While in usual commercial situations this feedback cycle is much longer due to the time consuming manual or automated testing of actual product behavior.
about 3 years ago
Interesting!
On the GPU compute side, we are completely dependent on running it on actual hardware. We usually try to modularize the code into small testable pieces, for which we write CPU reference implementations. In addition, we let the unit test force different code paths (disabling hardware features), as well as running benchmarks. Extremely useful for optimizations.
For geometry, we capture the produced geometry and compare it to reference geometry.
The full set of unit-tests take some time, but during development we only run a small subset. And for each commit the full set is run on a test server.
about 3 years ago
Yes, that is also a good direction.
However, writing the reference implementation you mentioned and all the checking and execution environment required for it needs a big initial effort.
My approach is not the holy grail of testing graphics applications just a neat trick to apply unit tests directly and relax the need for an actual API implementation.
What you are talking about is much more like the first approach presented in the article but with a more robust intelligent built-in the framework itself.
I bet it works in practice and I wouldn’t even advice to replace it but if you’ll ever require a lower level testing then the approach presented may come handy.
Anyway, thanks for sharing your experiences. I would be interested in any further details about your testing environment, especially from implementation point of view. You can e-mail me or continue commenting as it is nice to see that people have working automated graphics application testing frameworks and I’d like to know the details.
about 3 years ago
Some of us at my group are trying to work more in line with test-driven development, though, all the pieces aren’t completely in place yet. Though, we’ve made some progress.
In some cases, our task is to port existing numerical software to heterogeneous architectures. So the first step is to refactor the code into a layout that matches the efficient use of e.g. CUDA. Part of this process is to break down the computations into steps which can be verified to the original implementation. Here we use unit tests to verify that the results of intermediate computations etc. match the original implementation. We then port pieces of the refactored code onto the GPU, using unit tests again to maintain correctness. In this process, there are lots of changes in data management, so unit tests are quite valuable.
For pure GL projects, I either write a full reference for that part of the algorithm, or if I have a running GL version, I capture the geometry, read this back to the CPU, check the validity of meshes (e.g is the mesh a valid 2-manifold etc.), and if it is the first time I run the test, the result is stored in a file on disc which I inspect manually. Subsequent tests compare the geometry to the geometry in this file.
A tricky part of GL development is that the feature set of GPUs vary, as well as drivers have a bit of temper as well, so I maintain a few pipelines. Which pipeline that is used is determined at application setup, and I have a hook here for the unit tests to force a particular pipeline.
We use the Hudson integration server to manage the automation. It polls the repositories to check if anything has changed, and if so, it updates its copy of the source, compiles and runs the unit tests. Currently, only the CPU tests are run as this server doesn’t have a graphics card. But we are planning to run the graphics tests remotely, but haven’t gotten around to setting up the servers. At least with NVIDIA hardware, the Tesla and Quadro lines can run headless X-displays, so this should be quite straight-forward.
For the unit tests, we use gtest. The performance tests are run within this framework as well, as it can add extra properties to tests (avg. framerate in my case).
For testing bad OpenGL usage, your approach seems interesting. I currently rely on sequential numbering of GL resources to check if all vbos, shaders, textures etc. is correctly freed, an assumption that I am not convinced that is safe. In addition, the code is sprinkled with a lot of checks for GL errors when the code is built in debug mode. A wrapper like you describe would remove the need to have all these checks inside the code.
about 3 years ago
Your whole approach seems like the way driver integration test should be done. Very interesting!
Yes, in fact it’s a quite unfortunate situation that graphics developers have to deal with driver issues even in such cases where the OpenGL specification is clear enough.
About the GL error checking… I also use a macro to surround all GL calls in order to have this checking in case of debug compilation. It makes the code much harder to read, but I haven’t tried to eliminate the need of them. As you said, the layered fake driver that I was talking about can be implemented in a way that it simply passes through the call to the real OpenGL driver plus it also checks for GL errors. That can be e.g. a good plugin solution. By the way, I hadn’t do it yet, because I don’t really have the time to implement it.
about 3 years ago
Solution #2 and #3 seems nice for some basic fixed function style OpenGL applications, but hey, it’s 2010. Those obviously won’t work where heavy shader usage / postprocessing takes place, will they?
Besides, to me google mock seems like a way to test the code you’ve written, not the algorithm you’ve implemented with the code. E.g. let’s assume that the poor coder implemented the full rendering of some fractal in C++ (yes, he was silly enough to not do it in GLSL). Then, he tries to optimize his algorithm and starts running unit tests. Solution #1 can help, solution #2. maybe can be helpful, solution #3. fails big time – again. E.g. can you test if he makes an error in math calculation like miscalculation of a pixel’s color?
Also, the only thing i dislike about oh-so-trendy testing mechanisms/tools/whatever like google mock is that they seem so easy when the documentation shows a HelloWorld-like example, yet they can quickly became bloated beyond comprehension in real practice.
All in all, to me google mock doesn’t seem to be the way at all to test rendering algorithms. The fake driver is handy for debugging, but won’t help at all with shaders for example.
about 3 years ago
One more thing… You’ve written:
“Anyway, checking the actual rendering results on actual hardware is far beyond the scope of unit testing.”
Thinking in OpenGL 3.x – this is what you’ll test for 80% of the time when you test an OpenGL application, won’t you?
But i understand your point and the emphasis on “Unit testing”, however for the above reason, the very idea of Unit testing in case of OpenGL is weird. E.g. you can unit test for example a compression algorithm: your input is a byte array with length N and your otput is another byte array with length K < N. In case of OpenGL your input is a shader + some data passed through fixed function, your output is a rendered image/animation. Your fixed function calls can be fully OK, your states can be right in order, but yet you can render a beautiful fractal or a blank screen depending on how messed up your shader is
about 3 years ago
As I mentioned several times this is not about replacing traditional rendering testing methods, especially in case of shader-heavy applications, but a complementary tool to find coding errors in the very early stage of the development process.
I used different mocking libraries at my work and at my hobby projects too. Believe me, they are far more complex code bases than just HelloWorld-like examples. That’s exactly why I’ve chosen GoogleMock as it provides enough flexibility to cover almost all kind of use cases. Unit testing is not nice because it’s “oh-so-trendy” as you called it. It becomes more and more popular over time as it provides a great boost to the velocity of developers by decreasing maintenance time. It is not a coincidence that all important players in the industry like Google and Microsoft heavily rely on it nowadays. There are many case studies about the topic, you should look around.
I cannot emphasize enough! Unit test is for testing your code logic, not for testing actual rendering results. As an example, think about how much headache and additional time can a simple typing error (let’s say copy-pasting the wrong GL enum) cause in a code base that contains millions of lines of code. It is very difficult to debug the whole rendering stuff and find such a simple problem and unit test can definitely avoid these kind of situations. It is not my opinion, it’s a fact.
about 3 years ago
Forgot to mention… Currently I’m working in telecommunication where 99.999% availability of service is a MUST.
You should never underestimate the importance of automated testing and continuous integration!
Of course, graphics is not such a critical domain, so errors are much well received but if your code base is big enough you soon figure out that manual testing is far from satisfactory as even a change to a single line of code can crush the whole system if you aren’t careful enough and believe me, after a threshold no one is able to understand the whole code in all its details, especially when working together with hundreds or thousands of other developers on the project.
about 3 years ago
Hi, Your blog is really wonderful. I liked this article since it is very useful to me. Thanks for sharing it. Bye.
about 3 years ago
Well, i’m working in telecommunication too so i got the idea, trust me. Also, please point out where did i say that unit testing is not important or anything like that.
Just to make it clear, I’ve said two things:
1) Testing code that does rendering without letting to do it’s job is like testing a car’s engine without even igniting it
2) Year after year there are new tools which quickly become hyped-up, because their creator advertises them as THE solution for all your coding/testing/qm/design/whatever problem – later on they just go down like a piece of rock in the sea and everybody forgets them. (Again: i was talking about tools!)
Thanks for explaining unit testing, continous integration and other stuff anyway, but i use them anyway during my daily work and unfortunately that wasn’t the point of my post at all.
My point was that solution #1 – that you’ve actually referred as “naive”, “slow” and “expensive”, etc – is an important topic for several scientific reserches and you’re the one who underestimates something here
Namely, i’m talking about perceptual image comparison (http://pdiff.sourceforge.net/metric.html) as a testing method for graphic applications.
By the way now you keep saying that unit testing is for the early stage of development. Well, your OpenGL-based code mostly wont render anything in the early stage where you want to detect typing errors and such – in this case i don’t even see the point of mentioning solution #1.
But anyway, no offense of course, i just wanted to fill a logical hole in the otherwise nice article
about 3 years ago
By the way, perceptual image difference research is backed up by companies like Pixar. So its importance is not my opinion, it’s a fact.
about 3 years ago
Yes, I never said that image comparison is not an important phase of the testing of a graphics application.
Usually you need several levels of testing. The one you are talking about is a kind of integration or functional test, but that does not mean that you don’t need unit testing. Unit testing is for testing code level requirements and image comparison on actual hardware is for testing functional requirements. Two different levels, they are not against each other. Simply the feedback time is different.
In case of image comparison you actually test the real and full functionality, but the execution needs dedicated hardware and quite a lot of time as comparing images is not like comparing two integers. Unit testing is to provide limited verification capabilities that provide fast regression executions thus providing smaller feedback cycles and identification of a subset of possible problems in the early phase of the development.
Comparing two things that serve different purposes is simply non-sense.
about 3 years ago
I was saying it is a “naive” solution for unit testing as it wouldn’t be real unit testing not talked about functional testing…
Yes, you are right at this point. Mentioning solution #1 and actually the whole flow of finding a good solution is for the purpose of showing what wouldn’t be a suitable solution for unit testing and the reasons behind why we would like to take another step to find one. It is not for actual use, just illustrates the train of thought…
It is not easy to not take your posts as offense as we already heavily discussed about the topic with Chris (see above) so that checking for actual correct behavior on target hardware is a totally different story.
I don’t agree with this as think about a complex class that invokes OpenGL function calls several times. How would you test if this class does exactly what it has to without having to put it together with the whole system? You have to mock out the OpenGL API anyway or you choose to setup a working OpenGL context and environment for your class but then if a problem pops up it is difficult to decide whether the problem is in the environment setup or in the actual class you would like to test. Also, this makes your code tightly coupled with the environment setup code and that can heavily affect the maintenance costs of the testing environment.
about 3 years ago
Obviously you know a lot about it. I have been searching for this for a long time.
about 3 years ago
I am doing something similar to test my OpenGL code. Instead of introducing mock functions, I am introducint mock objects as template parameters. For example:
template
class render
{
public:
void doRendering()
{
OpenGLApi::glBegin( GL_POINT );
// vertex, texture, etc calls
OpenGLApi::glEnd();
}
};
For the real code, I have a class which just forward calls to the opengl functions, and in the unit tests I am checking the execution order (collecting them to the stringstream).
about 3 years ago
Forgot to mention : I tried the first approach, but with the off screen rendering, and comparing, but creating such unit tests is really hard and slow. And it can cause problems and wrong results if the unit tests are run with valgrind to check the memory access.
about 3 years ago
vj, your way of doing the test is the best way, however, it needs that all of your code should use the provided static class interface instead of the original OpenGL API functions, but if you start from straight the beginning then it is even better. Still, if you execute the actual OpenGL functions also in case of unit testing, then it’s more like an integration test. Anyway, your way of doing it is still nice in my opinion.
About comparing rendering results, well yes, it is not suitable for unit testing but can be a valuable tool in higher level testing mechanisms.
about 3 years ago
Interesting, but I would not encourage this approach. I would not even call this Unit Testing! It is more functional testing. The problem I have with it is that you are testing what you expect to be the implemnentation, allowing no freedom in how it is implemented. For all of my graphics applications, the constructor never makes any OpenGL calls. These are done lazily to ensure they are on the proper thread. So your simple example of the class Buffer would have a different test on my implementation than yours. If I decide to switch drawing from vertex arrays to VBO’s I have to change my tests.
The purpose of the tests to allow the implementations to be refactored / enhanced without too much worry about breaking the system. This seems to fail for your mock objects. There is a fundamental difference between say testing a encapsulated getter / setter pair in a class and the internal (non-public) order and set of OpenGL calls made in the implementation. If I change the getter, I can change the setter at the same time and the tests will still pass, regardless of what I did.
In summary, I think testing in this way is not a good idea and should be avoided. Sorry.
Roger
about 3 years ago
You are right from the point of difficulties regarding to refactoring and tight coupling between the test cases and the implementation. However, the purpose of this approach is to somehow ensure that the correct invocation orders happen.
Your example of switching from vertex arrays to VBOs should happen like the following:
- create the vertex array class and write the test cases for it to check correct OpenGL behavior
- think about how to introduce VBOs
- create abstract base class that vertex array and VBO inherit from
- create the VBO implementation with it’s own unit test set
- use the abstract base class in other modules as type and use factory pattern or whatever seems to be convenient
- simulate the vertex array/VBO functionality with mocks when testing other classes, so you don’t depend on any implementation details
Business logic shall always use abstract interfaces, not knowing the implementation details. For unit testing that particular vertex array/VBO class it is not a problem to have dependencies. Dependencies shall be avoided between modules and by using factory pattern and a mocking framework when doing unit test will solve the problem flawlessly.
about 3 years ago
Daniel Rakos wrote:
> Your example of switching from vertex arrays to VBOs should happen like the following:
The “should happen” is the crux of the problem. Your Unit Testing is dictating the implementation. I would not create a VBO class or a Vertex Array class. I instead might have a Cube class that was using glBegin and now I want to change it to a vertex array.
This is just a bad way to do this.
about 2 years ago
Really great information earlier i am bit skeptical of using testing in GL applications ,frankly i am not much aware of such GL platforms and very much confused in debugging,but after getting through to this post and some very good comments now i am bit confident and definatley try my hands on GL applications