Generateing a method via source code in pharo

164 views Asked by At

My goal is to generate a test method (automatically if we can say so). To do this, I need to send to a method that I named writeTestMethod., two parameters: the method I want to generate its test method from and a set of values ​​as the second. Once I send this, writeTestMethod will generate me the test method in which there are the assertions.

In the test method, I must be able to retrieve its class from the send method as a parameter. Once done, I initialize this class with its default constructor. And the second parameter is a set of values, with this set of values, I will initialize a new object of the same class but this time using the values. and at the level of the assertions, I will test if the two are equal.

I have a method that allows me to build the name of a test method but I can't write in it.

buildSelectorFor: aMethod
    ^ String streamContents: [:i || capitalize |
        capitalize := true.
        i << 'test'.
        aMethod selector do: [:charactar |
            charactar= $:
                ifTrue: [ capitalize := true ]
                ifFalse: [ capitalize
                            ifTrue: [ 
                                capitalize := false.
                                i << charactar asUppercase. ]
                            ifFalse:[ i << charactar ]]]]

so if I execute this method with this for example:

buildSelectorFor:Car>>#speed:mark:

I get this:

testSpeedMark

my goal is to get something like

testSpeedMark
    self assert:....equals:...

I added a method writeTestMethod.

writeTestMethod: aMethod with: anObject 
    ^(self buildTestSelectorFor: aMethod),'
      |classMethod setter instObject method|
      classMethod := aMethod methodClass.
    setter := (classMethod  allSelectorsInProtocol: #setter) asArray.
    instObject := classMethod new.
    (setter with: anObject do: [:set :ivar | instObject  perform: set with: ivar]).
     self assert: instObject class equals: (classMethod new) class.'

So here is what I get: enter image description here

I don't know how to integrate the parameters of writetestMethod in the code I want to generate

2

There are 2 answers

6
Leandro Caniglia On

Your question seems to indicate that you have a parametric template for creating source code, in this case, source code of tests methods, and a way to generate data that should be tested with the resulting methods.

  1. Write one method that receives the required parameters and answers with the source code of the desired method (it looks like you already know how to do this, see 3 bellow though)

  2. Install the method in aClass (a subclass of TestCase whose name I don't know). To do this, you can use aClass compile: source, where source was obtained in step 1.

  3. Add an ivar data to your testing class and a setter for it. Make sure that the source code generated in step 1 operates on the ivar data.

  4. For each piece of data you happen to generate create an instance of your testing class, set the ivar data accordingly and add the test to a newly created TestSuite (use TestSuite >> named: for this). Here you can use TestSuite >> addTest:.

  5. Run your suite with TestSuite >> run.

  6. To get rid of automatically created tests, should you want to do that, send removeSelector: to your testing class.

0
Be1dzr On

I think only you'd need to do is use: targetClass compile: 'source code of the method you want to have' source code is a string, so you can just format on whatever you want, e.g. I want to print {1}.' format: {'apples'} would result in: I want to print apples.