Creating temporary classes for testing

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Creating temporary classes for testing

Sean P. DeNigris
Administrator
I was playing with creating temporary classes for testing in a separate SystemDictionary, so I don't have to worry about removing them.  But I'm a little beyond the boundary of my knowledge (although I stepped through it in the debugger and it seemed pretty straight forward).  Are there any hidden side-effects/implications of the following?  Specifically, after the SystemDictionary is garbage collected, is the system exactly the same as it was before the code was run?  It seems like a better approach than creating them in the global namespace and cleaning up.

  testingEnvironment := SystemDictionary withOrganizer: SystemOrganizer new.

  ClassBuilder new
        name: #AClassForTesting
        inEnvironment: testingEnvironment
        subclassOf: Object
        type: Object typeOfClass
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        category: 'TemporaryTesting'.

  newClass := (testingEnvironment at: #AClassForTesting).
  newClass
        compile: 'greeting
                ^ ''hello there'''
        classified: 'greeting'.
       
  newClass new greeting. "Returns 'hello there'"

Thanks.
Sean
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: Creating temporary classes for testing

Noury Bouraqadi-2
Hi Sean,

For testing you can have two approaches:
-You need a mock object, and then you use a Mock library
-You want to test something related to classes, and in this case you can use the SUnit extension I introduced a while ago ClassFactoryForTestCase. It's part of the core image.

It supports the creation and the deletion of classes. To ensure keeping the system clean.

Noury
On 9 déc. 2010, at 17:00, Sean P. DeNigris wrote:

>
> I was playing with creating temporary classes for testing in a separate
> SystemDictionary, so I don't have to worry about removing them.  But I'm a
> little beyond the boundary of my knowledge (although I stepped through it in
> the debugger and it seemed pretty straight forward).  Are there any hidden
> side-effects/implications of the following?  Specifically, after the
> SystemDictionary is garbage collected, is the system exactly the same as it
> was before the code was run?  It seems like a better approach than creating
> them in the global namespace and cleaning up.
>
>  testingEnvironment := SystemDictionary withOrganizer: SystemOrganizer new.
>
>  ClassBuilder new
>        name: #AClassForTesting
>        inEnvironment: testingEnvironment
>        subclassOf: Object
>        type: Object typeOfClass
>        instanceVariableNames: ''
>        classVariableNames: ''
>        poolDictionaries: ''
>        category: 'TemporaryTesting'.
>
>  newClass := (testingEnvironment at: #AClassForTesting).
>  newClass
> compile: 'greeting
> ^ ''hello there'''
> classified: 'greeting'.
>
>  newClass new greeting. "Returns 'hello there'"
>
> Thanks.
> Sean
> --
> View this message in context: http://forum.world.st/Creating-temporary-classes-for-testing-tp3080408p3080408.html
> Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
>


Reply | Threaded
Open this post in threaded view
|

Re: Creating temporary classes for testing

Sean P. DeNigris
Administrator
Noury Bouraqadi-2 wrote
-You want to test something related to classes, and in this case you can use the SUnit extension I introduced a while ago ClassFactoryForTestCase. It's part of the core image.
Cool, that's it exactly.

Now I have two new questions:
*  What if ClassFactoryForTestCase used the separate-SystemDictionary approach?  Wouldn't you only need to clean up the logs and the classes would get gc-ed (even if cleanup was never called)?
*  Is my OP correct that it is safe to do what I was doing i.e. no effect to the system (except maybe the doit in the changes)?  (I may have another application for it)

Thanks.
Sean
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: Creating temporary classes for testing

Alexandre Bergel
This is something that I often need.
I have always addressed this as follows:
Added a 'classes' instance variable in my unit test. Added a bunch of methods such as:
createClassNamed: aSymbol superclass: aSuperclass instVarNames: instVarNames
        | cls |
        cls := aSuperclass subclass: aSymbol
                                instanceVariableNames: instVarNames
                                classVariableNames: ''
                                poolDictionaries: ''
                                category: 'Generated'.
        self classes add: cls.
        ^ cls

Then in the teardown I have something like:
tearDown
        super tearDown.
        classes ifNotNil: [:clss | clss do: #removeFromSystem ].

You may also want to remove the empty category in the tearDown.

Cheers,
Alexandre


On 9 Dec 2010, at 14:50, Sean P. DeNigris wrote:

>
>
> Noury Bouraqadi-2 wrote:
>>
>> -You want to test something related to classes, and in this case you can
>> use the SUnit extension I introduced a while ago ClassFactoryForTestCase.
>> It's part of the core image.
>>
>
> Cool, that's it exactly.
>
> Now I have two new questions:
> *  What if ClassFactoryForTestCase used the separate-SystemDictionary
> approach?  Wouldn't you only need to clean up the logs and the classes would
> get gc-ed (even if cleanup was never called)?
> *  Is my OP correct that it is safe to do what I was doing i.e. no effect to
> the system (except maybe the doit in the changes)?  (I may have another
> application for it)
>
> Thanks.
> Sean
> --
> View this message in context: http://forum.world.st/Creating-temporary-classes-for-testing-tp3080408p3080630.html
> Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
>

--
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
Alexandre Bergel  http://www.bergel.eu
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.






Reply | Threaded
Open this post in threaded view
|

Re: Creating temporary classes for testing

Noury Bouraqadi-2
In reply to this post by Sean P. DeNigris

On 9 déc. 2010, at 18:50, Sean P. DeNigris wrote:

> *  What if ClassFactoryForTestCase used the separate-SystemDictionary
> approach?  Wouldn't you only need to clean up the logs and the classes would
> get gc-ed (even if cleanup was never called)?


> *  Is my OP correct that it is safe to do what I was doing i.e. no effect to
> the system (except maybe the doit in the changes)?  (I may have another
> application for it)

Your usage of the classbuilder looks sound.
But, deleting your environment is not enough, at least not enough to ensure the deletion of your classes. You need :

-to delete all references to classes for your environment from their superclasses.
This is part of what is performed by the obsolete message.

-ensure that no instance of classes of your environement is referenced from root objects (e.g. default environment). Cause a class can't be GCed if its instances are still accessible.

Noury
Reply | Threaded
Open this post in threaded view
|

Re: Creating temporary classes for testing

Sean P. DeNigris
Administrator
Thanks, Noury.  I didn't understand one part:

Noury Bouraqadi-2 wrote
You need... to delete all references to classes for your environment from their superclasses.
This is part of what is performed by the obsolete message.
If I evaluated the code from my original post in a workspace, and then closed it, wouldn't everything go away when the temporary SystemDictionary (which contains the SystemOrganizer and newClass) was gc-ed?

Sean
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: Creating temporary classes for testing

Noury Bouraqadi-2

On 10 déc. 2010, at 02:15, Sean P. DeNigris wrote:

> Noury Bouraqadi-2 wrote:
>>
>> You need... to delete all references to classes for your environment from
>> their superclasses.
>> This is part of what is performed by the obsolete message.
>>
>
> If I evaluated the code from my original post in a workspace, and then
> closed it, wouldn't everything go away when the temporary SystemDictionary
> (which contains the SystemOrganizer and newClass) was gc-ed?
>
Object subclasses collection still includes a reference to the class you created in a different envirenment. It will never be GCed. So, this is a memory leak!

Noury


Reply | Threaded
Open this post in threaded view
|

Re: Creating temporary classes for testing

Luc Fabresse
Hi,

 You should look at : ClassFactoryWithOrganizationForTestCase
 I guess it is exactly what you are looking for.

 And also SystemNavigationTest and SystemNavigationOnNewlyCreatedEnvironmentTest that uses an instance of this above class.
 
#Luc


2010/12/10 Noury Bouraqadi <[hidden email]>

On 10 déc. 2010, at 02:15, Sean P. DeNigris wrote:
> Noury Bouraqadi-2 wrote:
>>
>> You need... to delete all references to classes for your environment from
>> their superclasses.
>> This is part of what is performed by the obsolete message.
>>
>
> If I evaluated the code from my original post in a workspace, and then
> closed it, wouldn't everything go away when the temporary SystemDictionary
> (which contains the SystemOrganizer and newClass) was gc-ed?
>
Object subclasses collection still includes a reference to the class you created in a different envirenment. It will never be GCed. So, this is a memory leak!

Noury



Reply | Threaded
Open this post in threaded view
|

Re: Creating temporary classes for testing

Sean P. DeNigris
Administrator
In reply to this post by Noury Bouraqadi-2
Noury Bouraqadi-2 wrote
Object subclasses collection still includes a reference to the class you created in a different envirenment. It will never be GCed. So, this is a memory leak!
Aha, okay now I understand:
  Object subclasses detect: [ :c | c name = #AClassForTesting ]. "Returns: AClassForTesting"

Thanks again, Noury.

Sean
Cheers,
Sean