Unit Testing Group

cancel
Showing results for 
Search instead for 
Did you mean: 

Unit test on private class method

I want to make a UT on a class VI that is a private class method with JKI's VI tester. Because the unit test VI is not a part of class scope of the class under test the run button is brokken.

As I se it i could temporary change the scope of the VI, make it public and if is is only for one VI it could be ok. But for many VI's this is not an option.

An other way could be to associate the class under test to the JKI test class and it could work, if you remember it.

Dos any one have any experience with this

/christian

0 Kudos
Message 1 of 11
(10,680 Views)

I'd be tempted to try the Community scope for the JKI tester to allow it access to the protected VIs of your class. However, I'll admit I've used Community scope before with multiple classes and XControls and found the feature to be less than perfect so it might cause future issues for you.

Alternatively, could you create unique test VIs in the class, effectively wrapper VIs, that are public? It bloats the class slightly, and you could probably find a way to make sure they're not accessible/callable from parent development code but only the JKI VI Tester?

Thoric (CLA, CLED, CTD and LabVIEW Champion)


Message 2 of 11
(8,518 Views)

This is a challenging scenario for which the proper answer is normally "you shouldn't" which I'm not completely sold on yet but am slowly being won over by.

Really what this means is that you should be able to test this through a public method. This means you only test the desired behaviour rather than the specific implementation which is more likely to change and break the tests.

That is not always the case but I would consider this approach first for maintainability.

James Mc
========
CLA and cRIO Fanatic
My writings on LabVIEW Development are at devs.wiresmithtech.com
Message 3 of 11
(8,518 Views)

I would also say "you shouldn't". You should test the public interface to a class. So, either the method is part of the public interface or it isn't a "unit of work" that you need to test. I would consider testing the public method that contains the private method instead.

Casey Lamers


Phoenix, LLC


casey.lamers@phoenixwi.com


CLA, LabVIEW Champion


Check Out the Software Engineering Processes, Architecture, and Design track at NIWeek. 2018 I guarantee you will learn things you can use daily! I will be presenting!

Message 4 of 11
(8,518 Views)

I've played this game before .

As James pointed out, it's a challenging scenario. I've seen several ways to deal with it, none of which are a perfect solution. And note, there's nothing particularly VI-Tester-centric about any of this. If you end up using a different unit test framework you can apply the same principles

Option #1: Don't Try To Unit Test Private Methods. Only Test Through The Public API.

I'm 100% in agreement with James on this one, and it's philosophically the most "correct." If you can't access a behavior through a public API, then by definition that behavior can't happen in a real-world use case so testing it is a waste of time. I used to be dead set against this, because frequently the functions I think are most critical are in private scope. But it's true.

Testing only through the public API tends to make your test code cleaner (because it matches the contract of your public API) and also simulates exactly how the bug you're testing will occur in the real world.

There are some practical exceptions to this (e.g. if the bug requires an internal state for your class that is really difficult to reach through the public API but easy to simulate in a direct call to the private member), but in general it really is a better way once you get used to it.

So when you're faced with the temptation to test a private method, ask yourself: Is there any way to realistically test this through the public API? There usually is, and in the long run it's well worth the effort.

Having said that, if you really want to take the path to the Dark Side....

Option #2: Create Wrapper VIs / Use Community Scope

Thoric's solution is usually my fallback if I can't live with Option #1. I sometimes create a "Unit Test Support" folder in my class, set it to Community scope, and then create VIs in there that are thin wrappers on whatever private code I'm trying to test.

You can then set your Unit Test class(es) to be a Friend of your class under test, so only your unit tests can access those methods.

Option #3: Use Scripting To Change Your Private VIs to Public, Test Them, Then Set Them Back

Someone gave a presentation on this at the 20152014 CLA Summit in Austin. Unfortunately I forget who it was at the moment and I don't want to blame the wrong person.

It is possible to use scripting code to programmatically change the scope of your private VI under test to Public, test it, then set it back to Private when you're done.

Please don't do this. There was as a working demo of this at the CLA Summit I mentioned, and I have to admit that it worked. But it strikes me as a very bad idea to have test code that modifies your source code at test time. Even if you take great pains to clean up after yourself, catch any failures that occur, or even test on a special read-only checkout of your source code control system, it just seems like there are better ways to test code than to modify it during testing.

But if that's how you want to roll, it's certainly possible .

EDIT: Fixed CLA Summit year.

Message 5 of 11
(8,518 Views)

One more vote for the don't go down the path of testing a private method.  A private method is more likely to change than a public method that is used by others.

One of the complaints I here from teams is that it is hard to keep up with the Unit Tests, that they become a burden rather than help, specially when refactoring large sections of code, when inspecting in more detail one can see that it is because the functionality of the "unit of work" rarely changes, but it is the implementation that changes.

However, if you do find that you still want to test the private method regardless of all the comments here, then just go for the route of taking advantage of JKI VI Tests being class based and use the Community Scope like Thoric suggested or create a public wrapper within your class. A third option that was presented last year at CLA Summit was to programmatically change the scope of the VI before and after the test is done, that third option does not sound clean to me at all, but it has been tried.

Hope this helps.

Regards,

Fab

For an opportunity to learn from experienced developers / entrepeneurs (Steve, Joerg, and Brian amongst them):
Check out DSH Pragmatic Software Development Workshop!

DQMH Lead Architect * DQMH Trusted Advisor * Certified LabVIEW Architect * Certified LabVIEW Embedded Developer * Certified Professional Instructor * LabVIEW Champion * Code Janitor

Have you been nice to future you?
Message 6 of 11
(8,518 Views)

Well obviously Fab and I think alike .

Message 7 of 11
(8,518 Views)

Hi,

I also am of the opininon of not doing unit test on private methods. I suppose that in these kind of scenarios the assertions may become very handy, you could verify your method using them and do the unit test of the public API?

0 Kudos
Message 8 of 11
(8,518 Views)

What I have tried to do in this situation is think about how I can test the public methods of my class which will call the private class method in question such that I can try and maximize coverage.

Most likely, your public facing methods should be fairly static (so as not to break the callers of your class down the road by changing API). Thus, if your test cases are geared more towards the use cases of the callers of your class, the test stays relevant for a longer period and you may find you'd get most of the benefit you would have gotten by way of private method unit tests.

0 Kudos
Message 9 of 11
(8,518 Views)

Another side-comment (I agree with all the other commenters here) - if you have an urge to test a particular private method then this often indicates that the method in question is doing enough work to warrant refactoring this out into it's own scope / class and then delegating to this in the original public methods. That new extracted method can be made public and thus easily testable by the framework of your choice.

Message 10 of 11
(8,518 Views)