TDD in C ++. How can I test the functions of a private class friend?
if i have a class with a private member class inside it like this
class Obj;
class Helper {
friend class Obj;
private:
int m_count;
Helper(){ m_count = 0;}; // Note this is a private constructor
void incrementCount(){
++m_count;
};
};
class Obj {
Helper *m_pHelper;
// note that this is a private getter
int getHelperCount() { return m_pHelper->m_count; };
// the public API starts here
public:
Obj() { m_pHelper = new Helper(); };
void incrementCount(){ m_pHelper->incrementCount(); };
};
So how can I TDD such a system?
auto obj = new Obj();
obj->incrementCount();
// what to assert???
This is my question, and here are just a few.
Answer to some of the answers and comments.
If you are not interested in anyone outside the classroom, your tests should not be interesting either. - Arne Merz
If nobody is interested in the value outside the class why are you utnapistim
Even if none of the parties need this value, I still want to know that if it is configured correctly as it is being used by another internal internal method of the class using this value. Perhaps this is the value that the controller will use to update the model. Or maybe this is the position at which the view will be used to draw something on the screen. And in fact, all other Obj components will be able to access this variable. It might be bad design, in which case I would like to know what are the best alternatives I can have. The design is listed in the background section at the bottom of this post.
Identify the Private Public - Marson Mao
Love this ingenious misuse of keywords haha. But it cannot be completed as the best solution. Yet
You need to "expose" the friendship relationship in your class header. Thus, you must acknowledge the existence of the class used to validate your. If you are using the pImpl idiom you can make all members of pImpl public, pImpl itself and give your unit tests access to pImpl - CashCow
Does this mean that I have to compare the test in my original class? Or add additional "test" methods to it? I recently started TDD. Is it common (or better, good) to tamper with the original class with a test class dependency? I don't think I have the relevant knowledge to judge. Any advice on this?
Misc: AFAIK TDD is not just a test recording, but a development process. I read that I should only write tests for the public interface. But the problem is that, as in the situation, most of the codes, etc. Contained in a private classroom. How can I use TDD to generate these codes?
Background
FYI, if you want to know why I am making a private class: I am developing a game from cocos2dx. The game engine uses the Node tree structure for updates, rendering, etc., and each game object inherits from the Node class provided in the engine. Now I want to implement an MVC pattern for a game object. So for each object, I basically created an Object class with 3 helper classes corresponding to each of the MVC components named ObjectModel, ObjectView, ObjectController. In theory, no one should directly access the MVC classes and will only be accessible in some way through the Object class, so I make them 3 private. The reason is clearly that the MVC components are clearly classes, because the View and Controller update at different rates (more precisely, Controller does frame-specific updates,while View does simple interpolation based on model data). The model class is created purely for religious reasons.
Thanks in advance.
source to share
The private public trick #define can have side effects with the way some compilers are control function symbols (Visual C ++ - the compiler includes an access specifier in its name)
You can also change the visibility with the using statement:
struct ObjTest : public Obj
{
using Obj::incrementCount;
}
But like other people, try not to check personal items if possible.
How can I test the functions of a private class friend?
Do not!
A class (or module or library or whatever) provides a public interface for some reason. You have a public interface (which is meant to be used by the client, so it has invariants, preconditions, postconditions, side effects, whatever - that can and should be tested) and the implementation details that allow you to implement the public interface are easier.
The point of private implementation is that you are allowed to modify it as you see fit without affecting other code (not even affecting the tests). All tests should pass after you change your private implementation, and the client (and test) code should (by design) not care at all about you changing the private implementation.
So how can I TDD such a system?
TDD for your public interface only. Testing the implementation details means that you end up coding the implementation, not the interface.
Regarding your comment:
The problem is I don't even have a getter in the public interface. So how can my test check if the value is 0 or 1? And the getter is intentionally made private, since no one should be interested in the value outside the class
If no one is interested in the value outside of the class, why would you (i.e. why would you want to check it?)
source to share
I got this kind of problem when I was writing a unit test.
After some searching, I figured the most efficient way is to add this to my Test.cpp
:
#define private public
NOTE. Add this before your desired include file, maybe yours Obj.h
for example.
I think this method looks crazy, but it really makes sense because this one #define
only affects your test file, so everyone else using yours Obj.h
is totally fine.
Some link:
source to share
I vote, as @Marson Mao says, for the #define of the private public.
If you want to control what to make private or public a little more, you can do that in yourtests.cpp file
#define private public
#include "IWantAccessViolationForThis.h"
#undef private
#include "NormalFile.h"
This way you can get a little more control and try to do this trick in as few places as possible.
Another nice thing about this approach is that it is not intrusive, which means you don't have to clutter your real implementation and header files with #ifdefs for testing, not testing.
source to share
Your friend has full access to the class that he is a friend. This can be done for many reasons, and one of them might very well be for unit testing , i.e. You want to write a unit test that can call the private members of the class and check the internal variables to show what you expect from them, but you don't want this to be part of the public API.
You need to "expose" the friendship relationship in your class header. Thus, you must acknowledge the existence of the class used to validate your. Don't worry, you are developing in the real world and the classes are being tested.
To write a unit test, you will want to implement this class to provide protected member functions (maybe static ones) that call all the corresponding private functions or get private members, and then you write classes that derive from yours. Note that they have there will be no direct access since friendship is not inherited, hence the static protected members.
If you are using the pImpl idiom, you can make all the members of pImpl public, pImpl itself, and give your unit tests access to pImpl (via the same model as above). This is easier now because you only need to create one method for your "tester".
As for the data members of the class, in recent years, as you know, I put all this in a structure, i.e. had them all publicly and then for the class to have a private instance of that struct. It might be easier to handle this sort of thing as well as serialization / factories for your class where they can create a structure that is public and then build a class from it.
source to share