EUnit question

How do I create a private accessor with EUnit, so I can test private members?

I don’t believe there’s a way to test private members, for now. we’d need something like Swift’s “testable” visibility to make private members public for testing purposes only. Something we might look at in the future,…

What I am used to: How to test a Private Method

But I will use reflection for the moment.

interesting. i’ll need to check out what that does. i assume it probably generates wrappers that use Reflection internally? I’m wondering if we can solve this better, compiler side. by just letting the compiler promote the visibility, for the test class only. i’ll log a research issue.

Thanks, logged as bugs://80263

@mh ,

I just let my imagination run free - how would testing be really easy…

When I create a new project at this moment, I get 2 compile configurations; Debug and Release.
I think there should be a third: Test - I will come back to this later.

As I understand EUnit (and the microsoft test framework), I have to create a specific test project, and in there the test classes. Because this is a seperate project, tesing of internal/private classes and functions is very hard.

When I could add the test methods to the implementation itself, everything would be easyly testable.

An example:

type MyTestableType = Class
  private 
    method MyPrivateMethod(s: String);

    //will only be compiled into the assembly when the configuration is Test
    //no parameters allowed
    method MyPrivateTestMethod; test;
end;

implementation

method MyTestableType.MyPrivateMethod(s:String);
require
  //require contract
begin
  //the implementation code
ensure
  //ensure contract
end;

method MyPrivateTestMethod;
begin
  //the test code to test MyTestableType.MyPrivateMethod
  //test fails when an exception is raised but not catched within this function
end;

end.

To run the tests, just compile for Test.

Edit:
A test visibility would even be better:

type MyTestableType = Class
  test
    //will only be compiled into the assembly when the configuration is Test
    //no parameters allowed
    method MyPrivateTestMethod;
  private 
    method MyPrivateMethod(s: String);
end;

On the question of test visibility, is this really much more convenient than simply having a public method which is conditionally compiled when DEBUG (or TEST) is defined ?

type MyTestableType = Class
  {$IF TEST}
  public
    method MyPrivateTestMethod;
  {$ENDIF}
  private 
    method MyPrivateMethod(s: String);
end;

Caveat: Not sure if this works with the new “#if redefined” in Elements 10 (I’m unable to test right now and haven’t moved up to 10 yet to have sufficient experience to draw on).

Having said that, I’m yet to be convinced that there is a watertight case for testing private methods, vs testing public methods which exercise the necessary implementation details (including but not limited to private methods etc). If there is sufficient concern/complexity in the private methods that they need to be tested separately then I often find that in fact one (or usually more) such private methods are really obfuscating the need for a separate class (which once identified can then be tested via the public methods it provides).

In fact, this happened to me just yesterday when I found that was having difficulty testing aspects of private details of a class and came to the realisation that the real problem was that I actually needed a wholly new class to encapsulate those private details.

As a result I now have code that is testable in the way that I need and a much better design/architecture overall. Win Win! :slight_smile:

What I see is, say a [Testable] aspect, you could apply to methods. when building in test config, that would upgrade the visibility as needed, and make for much cleaner code that having extra {$IF TEST} all over the place. But we’ll see — this is something we’ll need top research how to best support, long term…

True. by definition, a unit test should test public APIs. But that said, I still do see how this could be very convenient, to have tests for private methods as well. especially with Fire/Water’s deep EUnit integration where you just press Cmd-T and see your test results inline…

I do not agree.

I use the test-before-implement method:

  1. write the unit test first to define the expected behavior of the method that is being build
  2. write the method and test it until the tests succeed.

Every method should have a simple and clear predefined behavior - and that behavior is defined and ensured by a test method. And that is true for private, protected, unit, public or whatever visibility.

And whenever a new bug is detected in the software, a test for this bug has to be added - first add a test that reproduces this bug (on the deepest level, on the method that contains the bug). And then solve the bug (which means that the new test succeeds without a failure of any other (earlier defined) test).

The problem with “only public” tests is that, the higher you come in the call tree, the more complex the solved problem becomes - which makes it exponential more difficult to define good tests that cover all possibilities.

Unit tests serve several purposes:

  1. Define the behavior of each method.
  2. Ensure that refactoring does not change the defined behavior
  3. Ensure that a bug fix only fixes the bug instead of breaking previously working behavior.
  4. Proof that the public functionality is in line with the specifications

Points 1 to 3 works for all methods with any visibility.
Point 4 is only for the public API.

I don’t disagree. I was just being anal out the term unit test. technically, of you’re testing your private methods, you’re not unkit testing, you’re just testing. Which is fine and should be done, of course. :wink:

But the term unit test comes from the idea that you get a black box and you confirm it works, as a unit, as spec’ed — no matter how it does that, internally.

That said, despite the name, EUnit should facilitate this level of testing, of course, and we’ll look into what the best solution might be.

1 Like

You are probably right; as I have no degree in computer science.
But I learned this in my career as test driven development, where unit stands for the smallest unit of code: the method. And it works to build very predictable, maintainable and extendable software.

No hurry - for this moment reflection works perfect.

1 Like

Marc, for the roadmap:

  • Private accessors
  • Shims
  • Fakes
  • Code coverage

bugs://E21443 was closed as fixed.