Search code examples
unit-testingvisual-foxpro

Can a VFP class get a collection of it's own methods at run-time?


Here's what I'm trying to accomplish, in Visual FoxPro. I want to write a parent UnitTest class, that can be subclassed to create individual unit tests. I am hoping that the parent UnitTest can have a MainMethod which examines itself, and then finds and executes all of it's own methods which begin with "test_".

This way I can go forward writing appropriately named functions in my unit tests, and the parent will know how to run them without any additional input from me. But, I can't locate any way to get this information from VFP at run-time, without having the child class explicitly define a collection of method names or something to that regard (which is exactly what I'm hoping to avoid).

Here's is a basic stub:

define class UnitTest as custom  && would be abstract if VFP supported that

    procedure MainMethod()
        && run all methods that begin with test_
    endproc

enddefine

define class AUnitTest as UnitTest

    procedure test_thingA()
        ...
    endproc

    procedure test_thingB()
        ...
    endproc

enddefine

Would love anyone's ideas on how to get at the child methods from the parent. (Also open to a better implementation idea, if I'm going about this wrong, I think the basic idea of what I'm going for is clear).

Thanks so much in advance!


Solution

  • The AMEMBERS() function could be used to get a list of methods.

    loX = CREATEOBJECT("AUnitTest")
    loX.MainMethod()
    STORE .NULL. TO loX
    RETURN
    
    
    define class UnitTest as custom
    
        procedure MainMethod()
            LOCAL lcCommand, lcName, lcType, lnMemberNo, lnTotalMembers
            LOCAL ARRAY laMembers(1)
    
            m.lnTotalMembers = AMEMBERS(laMembers, THIS, 1, "U")
            FOR m.lnMemberNo = 1 TO m.lnTotalMembers
                m.lcName = m.laMembers[m.lnMemberNo,1]
                m.lcType = m.laMembers[m.lnMemberNo,2]
    
                IF (m.lcType == "Method") AND (LEFT(m.lcName, 5) == "TEST_")
                    m.lcCommand = "THIS." + m.lcName + "()"
                    &lcCommand
                ELSE
                    * do nothing
                ENDIF
            ENDFOR
    
        endproc
    
    enddefine
    
    define class AUnitTest as UnitTest
    
        procedure test_thingA()
            WAIT WINDOW "Testing Thing A"
        endproc
    
        procedure test_thingB()
            WAIT WINDOW "Testing Thing B"
        endproc
    
        procedure NotATest()
            WAIT WINDOW "Not A Test"
        endproc
    
    enddefine