What Is Wrong with Making a Unit Test a Friend of the Class It Is Testing

What is wrong with making a unit test a friend of the class it is testing?

Ideally, you shouldn't need to unit test private methods at all. All a consumer of your class should care about is the public interface, so that's what you should test. If a private method has a bug, it should be caught by a unit test that invokes some public method on the class which eventually ends up calling the buggy private method. If a bug manages to slip by, this indicates that your test cases don't fully reflect the contract you wish your class to implement. The solution to this problem is almost certainly to test public methods with more scrutiny, not to have your test cases dig into the class's implementation details.

Again, this is the ideal case. In the real world, things may not always be so clear, and having a unit testing class be a friend of the class it tests might be acceptable, or even desirable. Still, it's probably not something you want to do all the time. If it seems to come up often enough, that might a sign that your classes are too large and/or performing too many tasks. If so, further subdividing them by refactoring complex sets of private methods into separate classes should help remove the need for unit tests to know about implementation details.

Unit test a class declared friend (internal)

Add this to your AssemblyInfo.cs file:

[assembly:InternalsVisibleTo("YourOtherAssembly")]

This will make your internal assemblies visible to YourOtherAssembly. However, you should really consider if you need to have it internal. When writing tests try focusing on your public parts.

Read more here: http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx

Using a friend class vs. adding accessors for unit testing in C++?

Unit tests should 95% of the time only test the publicly exposed surface of a class. If you're testing something under the covers, that's testing implementation details, which is inherently fragile, because you should be able to easily change implementation and still have the tests work. Not only is it fragile, but you could also be tempted into testing things that aren't actually possible in planned usage scenarios, which is a waste of time.

If the point of the accessors you want to add is just to test whether the function had the desired effect, your class design may violate another principle, which is that a state-machine-like class should always make it clear what state its in, if that affects what happens when people interact with the class. In that case, it'd be right to provide those read-only accessors. If it doesn't affect the class's behavior, refer back to my previous bit about implementation details.

And as you rightly said, cluttering up the public surface of a class with unused stuff is also undesirable for its own reasons.

If I had to pick between accessors and friending in your case, I would choose friending, simply because you own your test and can change it in a pinch. You may not own the code by the clown who finds a way to use your extra accessors, and then you'll be stuck.

How can I test private members and methods of classes?

Well, unit testing should test units and ideally every class is a self-contained unit – this follows directly from the single responsibility principle.

So testing private members of a class shouldn’t be necessary – the class is a black box that can be covered in a unit test as-is.

On the other hand, this isn’t always true, and sometimes with good reasons (for instance, several methods of the class could rely on a private utility function that should be tested). One very simple, very crufty but ultimately successful solution is to put the following into your unit-test file, before including the header that defines your class:

#define private public

Of course, this destroys encapsulation and is evil. But for testing, it serves the purpose.

How to make google-test classes friends with my classes?

Try this (straight from Google Test docs...):

FRIEND_TEST(TestCaseName, TestName);

For example:

// foo.h
#include <gtest/gtest_prod.h>

// Defines FRIEND_TEST.
class Foo {
...
private:
FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
int Bar(void* x);
};

// foo_test.cc
...
TEST(FooTest, BarReturnsZeroOnNull) {
Foo foo;
EXPECT_EQ(0, foo.Bar(NULL));
// Uses Foo's private member Bar().
}

Unit testing c++. How to test private members?

Typically, one only tests the public interface as discussed in the question's comments.

There are times however when it is helpful to test private or protected methods. For example, the implementation may have some non-trivial complexities that are hidden from users and that can be tested more precisely with access to non-public members. Often it's better to figure out a way to remove that complexity or figure out how to expose the relevant portions publicly, but not always.

One way to allow unit tests access to non-public members is via the friend construct.

Testing private class member in C++ without friend

What will follow is not technically speaking a straight answer to your
question as it will still make use of the "friend" functionality
but it does not require modification of the tested entity itself
and I think it addesses the concern of breaking the encapsulation
mentioned in some of the other answers; it does though require
writing some boilerplate code.

The idea behind it is not mine and the implementation is
entirely based on a trick presented and explained by litb on his
blog(coupled with this Sutter's gotw for just a little bit
more context, at least for me) - in short CRTP, friends, ADL and pointers to members
(I must confess that to my dismay the ADL part I still don't
get it entirely, but I'm relentesly working in figuring it out 100%).

I tested it with gcc 4.6, clang 3.1 and VS2010 compilers and it
works perfectly.

/* test_tag.h */
#ifndef TEST_TAG_H_INCLUDED_
#define TEST_TAG_H_INCLUDED_

template <typename Tag, typename Tag::type M>
struct Rob
{
friend typename Tag::type get(Tag)
{
return M;
}
};

template <typename Tag, typename Member>
struct TagBase
{
typedef Member type;
friend type get(Tag);
};

#endif /* TEST_TAG_H_INCLUDED_ */

/* tested_class.h */
#ifndef TESTED_CLASS_H_INCLUDED_
#define TESTED_CLASS_H_INCLUDED_

#include <string>

struct tested_class
{
tested_class(int i, const char* descr) : i_(i), descr_(descr) { }

private:
int i_;
std::string descr_;
};

/* with or without the macros or even in a different file */
# ifdef TESTING_ENABLED
# include "test_tag.h"

struct tested_class_i : TagBase<tested_class_i, int tested_class::*> { };
struct tested_class_descr : TagBase<tested_class_descr, const std::string tested_class::*> { };

template struct Rob<tested_class_i, &tested_class::i_>;
template struct Rob<tested_class_descr, &tested_class::descr_>;

# endif

#endif /* TESTED_CLASS_H_INCLUDED_ */

/* test_access.cpp */
#include "tested_class.h"

#include <cstdlib>
#include <iostream>
#include <sstream>

#define STRINGIZE0(text) #text
#define STRINGIZE(text) STRINGIZE0(text)

int assert_handler(const char* expr, const char* theFile, int theLine)
{
std::stringstream message;
message << "Assertion " << expr << " failed in " << theFile << " at line " << theLine;
message << "." << std::endl;
std::cerr << message.str();

return 1;
}

#define ASSERT_HALT() exit(__LINE__)

#define ASSERT_EQUALS(lhs, rhs) ((void)(!((lhs) == (rhs)) && assert_handler(STRINGIZE((lhs == rhs)), __FILE__, __LINE__) && (ASSERT_HALT(), 1)))

int main()
{
tested_class foo(35, "Some foo!");

// the bind pointer to member by object reference could
// be further wrapped in some "nice" macros
std::cout << " Class guts: " << foo.*get(tested_class_i()) << " - " << foo.*get(tested_class_descr()) << std::endl;
ASSERT_EQUALS(35, foo.*get(tested_class_i()));
ASSERT_EQUALS("Some foo!", foo.*get(tested_class_descr()));

ASSERT_EQUALS(80, foo.*get(tested_class_i()));

return 0;
}

Why is a friend class not verified for existence?

A friend class declaration that uses an elaborated type specifier with non-qualified name of the class is actually a declaration of that class. It introduces the class as a member of the enclosing namespace. It does not require it to be pre-declared

class C
{
friend class X; // OK, introduces '::X'
};

But if you use a qualified name in a friend class declaration, it will be subjected to a regular qualified name lookup. And it must refer to a previously declared name

class X {};

class C
{
friend ::X; // OK, refers to '::X'
friend ::Y; // Error, no '::Y' in sight
};

So, if you want your class name to be "verified for existence", use qualified names in friend declarations.



Related Topics



Leave a reply



Submit