How to make internal/helper functions testable?

前端 未结 2 702
失恋的感觉
失恋的感觉 2021-01-14 10:42

Suppose that I have some function Foo that uses two internal helper functions bar and baz.

Is there a way to organize the code

相关标签:
2条回答
  • 2021-01-14 11:21

    Not the most elegant way to do it but then Matlab is not the most practical language to build modules in a single code file. One way to do it is to have a higher level level function which transfer the input arguments to the function you choose:

    function out = fooModule( FunctionCalled , varargin)
    %// This main function only transfer the input argument to the function chosen
    
       switch FunctionCalled
          case 'main'
             out = foo(varargin) ;
    
          case 'bar'
             out = mBar(varargin) ;
          case 'baz'
             out = mBaz(varargin) ;
       end  
    end
    
    function outFoo = foo(varargin)
       %// your main FOO code
       %// which can call the helper function if necessary
    end
    
    function outbar = mBar(varargin)
        %// your code
    end
    
    function outbaz = mBaz(varargin)
       %//  your code
    end
    

    You can even embed the FunctionCalled parameter into varargin if you want to compact things. This would also allow to test the type of the first argument. So for example if the first argument is not a string (calling one of the helper function) then forward the execution directly to the main foo function without having to call it explicitly (so the helper functions remain 'out of sight' if not called explicitly).


    Otherwise, a completely different approach, you could consider writing a class.

    0 讨论(0)
  • 2021-01-14 11:33

    There are a few options to achieve this.

    First, does Foo need to be a function? If it is a class then you can implement bar and baz as Hidden and Access='protected' which is pretty tightly locked down. Then you can create a test specific subclass that accesses bar and baz for testing. You can also scope the access to the test to further lock it from others view if desired.

    If you do want Foo to be a function then you still have options. One of those is to somehow get a function handle to the private local functions to your tests. You can do this through some special calling syntax of Foo that returns these functions to a test when called. This however, modifies the production code in a potentially confusing way, and it essentially inserts test logic into production. I would prefer hiding these functions by putting them into a package so that they are not in the global namespace. The name of the package can indicate that they are off limits and not part of your supported interface.

    Finally, one option is to simply use the public interface in order to test these functions. Clearly they are called from the function in some scenario. You may want to consider writing a test through the front door of your interface. One benefit of this is that you would then be able to change the implementation of your local function structure easily without modifying your test. The private functions are private because by definition they are part of your implementation, not your interface. If you find it complex enough to require its own test independent from the interface of Foo then it should probably just be broken out into another package function or class as described above in order to unit test it.

    0 讨论(0)
提交回复
热议问题