[Pharo-project] Creating temporary classes for testing
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-tp3080408p30804... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
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-tp3080408p30804... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
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-tp3080408p30806... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
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-tp3080408p30806... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
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
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 -- View this message in context: http://forum.world.st/Creating-temporary-classes-for-testing-tp3080408p30812... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
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
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 <bouraqadi@gmail.com>
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
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 -- View this message in context: http://forum.world.st/Creating-temporary-classes-for-testing-tp3080408p30821... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
participants (4)
-
Alexandre Bergel -
Luc Fabresse -
Noury Bouraqadi -
Sean P. DeNigris