A new version of SUnitTools was added to project The Inbox: http://source.squeak.org/inbox/SUnitTools-jr.5.mcz
==================== Summary ====================
Name: SUnitTools-jr.5 Author: jr Time: 5 March 2020, 9:53:04.92876 pm UUID: 612a0a0e-43fa-de40-8370-f5e90d767232 Ancestors: SUnitTools-tcj.4
Allow to create a new test class immediately if none is found.
=============== Diff against SUnitTools-tcj.4 ===============
Item was added: + ----- Method: CodeHolder>>testAskToCreateNewTest: (in category '*SUnitTools-running') ----- + testAskToCreateNewTest: className + (self confirm: 'Test class not found. Create one?') ifFalse: [^ false]. + (ClassBuilder new) + name: className asSymbol + inEnvironment: self selectedClass environment + subclassOf: TestCase + type: #normal + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: + ((self selectedClass category includes: $-) + ifTrue: [((self selectedClass category copyUpToLast: $-), '-Tests')] + ifFalse: [(self selectedClass category, 'Tests')]) asSymbol. + ^ true!
Item was changed: ----- Method: CodeHolder>>testBrowseClassNamed:possibleMessageNamed: (in category '*SUnitTools-running') ----- testBrowseClassNamed: aClassName possibleMessageNamed: aMessageName | cls selector | + (self class environment hasClassNamed: aClassName) ifFalse: + [(self testAskToCreateNewTest: aClassName) ifFalse: [^ self]]. - (self class environment hasClassNamed: aClassName) ifFalse: ["no dice" ^ self]. cls := self class environment classNamed: aClassName.
(aMessageName notNil and: [cls includesLocalSelector: (selector := aMessageName asSymbol)]) ifTrue: [ToolSet browse: cls selector: selector] ifFalse: [ToolSet browseClass: cls].!
Nice idea, even though you forget to have the message #translated :-)
What is the reason to use ClassBuilder instead of #subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:?
Best,
Christoph
________________________________ Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von commits@source.squeak.org commits@source.squeak.org Gesendet: Donnerstag, 5. März 2020 21:53:02 An: squeak-dev@lists.squeakfoundation.org Betreff: [squeak-dev] The Inbox: SUnitTools-jr.5.mcz
A new version of SUnitTools was added to project The Inbox: http://source.squeak.org/inbox/SUnitTools-jr.5.mcz
==================== Summary ====================
Name: SUnitTools-jr.5 Author: jr Time: 5 March 2020, 9:53:04.92876 pm UUID: 612a0a0e-43fa-de40-8370-f5e90d767232 Ancestors: SUnitTools-tcj.4
Allow to create a new test class immediately if none is found.
=============== Diff against SUnitTools-tcj.4 ===============
Item was added: + ----- Method: CodeHolder>>testAskToCreateNewTest: (in category '*SUnitTools-running') ----- + testAskToCreateNewTest: className + (self confirm: 'Test class not found. Create one?') ifFalse: [^ false]. + (ClassBuilder new) + name: className asSymbol + inEnvironment: self selectedClass environment + subclassOf: TestCase + type: #normal + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: + ((self selectedClass category includes: $-) + ifTrue: [((self selectedClass category copyUpToLast: $-), '-Tests')] + ifFalse: [(self selectedClass category, 'Tests')]) asSymbol. + ^ true!
Item was changed: ----- Method: CodeHolder>>testBrowseClassNamed:possibleMessageNamed: (in category '*SUnitTools-running') ----- testBrowseClassNamed: aClassName possibleMessageNamed: aMessageName
| cls selector | + (self class environment hasClassNamed: aClassName) ifFalse: + [(self testAskToCreateNewTest: aClassName) ifFalse: [^ self]]. - (self class environment hasClassNamed: aClassName) ifFalse: ["no dice" ^ self]. cls := self class environment classNamed: aClassName.
(aMessageName notNil and: [cls includesLocalSelector: (selector := aMessageName asSymbol)]) ifTrue: [ToolSet browse: cls selector: selector] ifFalse: [ToolSet browseClass: cls].!
Thiede, Christoph Christoph.Thiede@student.hpi.uni-potsdam.de schrieb am Sa., 7. März 2020, 14:31:
What is the reason to use ClassBuilder instead of #subclass: instanceVariableNames:classVariableNames:poolDictionaries:category:?
The ability to specify the target environment.
Ah, ok :-)
http://www.hpi.de/ ________________________________ Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Jakob Reschke forums.jakob@resfarm.de Gesendet: Samstag, 7. März 2020 14:57:12 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Inbox: SUnitTools-jr.5.mcz
Thiede, Christoph <Christoph.Thiede@student.hpi.uni-potsdam.demailto:Christoph.Thiede@student.hpi.uni-potsdam.de> schrieb am Sa., 7. März 2020, 14:31:
What is the reason to use ClassBuilder instead of #subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:?
The ability to specify the target environment.
Hi Jakob,
while reviewing this patch, I noticed that the category heuristic does not work in all situations. For example, it classifies a newly created WideSymbolTest under Collections-Tests rather than CollectionTests-Text. Do you have an idea how to improve the heuristic (e.g., search for other test classes in the same package, ...)? :)
Best, Christoph
--- Sent from Squeak Inbox Talk
On 2020-03-07T14:08:02+00:00, christoph.thiede@student.hpi.uni-potsdam.de wrote:
Ah, ok :-)
http://www.hpi.de/ ________________________________ Von: Squeak-dev <squeak-dev-bounces at lists.squeakfoundation.org> im Auftrag von Jakob Reschke <forums.jakob at resfarm.de> Gesendet: Samstag, 7. März 2020 14:57:12 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Inbox: SUnitTools-jr.5.mcz
Thiede, Christoph <Christoph.Thiede at student.hpi.uni-potsdam.de<mailto:Christoph.Thiede at student.hpi.uni-potsdam.de>> schrieb am Sa., 7. März 2020, 14:31:
What is the reason to use ClassBuilder instead of #subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:?
The ability to specify the target environment.
Since there are so many different combinations you can probably make this arbitrarily complex. Then 7/8 of the feature are the guessing of the category. The question is whether it is worth it.
You could search all registered packages that start with the same stem for subclasses of TestCase. That may introduce some unwanted dependency between trunk packages, so you may want to stick to categories rather than packages instead. You may program for the known patterns, so add your *Tests-* pattern to the list. Which one comes next? If there is no existing test category with the stem, which of the conventions do you choose?
Per KISS I would stick to just one convention, which can also be the one you mentioned rather than the one I implemented. Changing the category of the class afterwards should be easy enough.
christoph.thiede@student.hpi.uni-potsdam.de schrieb am Mo., 10. Jan. 2022, 18:02:
Hi Jakob,
while reviewing this patch, I noticed that the category heuristic does not work in all situations. For example, it classifies a newly created WideSymbolTest under Collections-Tests rather than CollectionTests-Text. Do you have an idea how to improve the heuristic (e.g., search for other test classes in the same package, ...)? :)
Best, Christoph
*Sent from **Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk*
On 2020-03-07T14:08:02+00:00, christoph.thiede@student.hpi.uni-potsdam.de wrote:
Ah, ok :-)
http://www.hpi.de/ ________________________________ Von: Squeak-dev <squeak-dev-bounces at lists.squeakfoundation.org> im
Auftrag von Jakob Reschke <forums.jakob at resfarm.de>
Gesendet: Samstag, 7. März 2020 14:57:12 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Inbox: SUnitTools-jr.5.mcz
Thiede, Christoph <Christoph.Thiede at student.hpi.uni-potsdam.de
<mailto:Christoph.Thiede at student.hpi.uni-potsdam.de>> schrieb am Sa., 7. März 2020, 14:31:
What is the reason to use ClassBuilder instead of
#subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:?
The ability to specify the target environment.
Hi Jakob,
please find the attached changeset, which revises the changes, allows the user to edit the new test case definition before creating it, and uses the 'KernelTests-Objects' pattern for test category derivation which is known from most Trunk packages. No further heuristics for related class search are included. I also revised the logic for subclass templates in the Kernel package a bit. If you like it, I can merge it into the Trunk. :-)
(At a later point in time, we might want to create a hook in the ToolSet for creating a new subclass and also make use of it in Parser>>#defineClass:. But for now, I think the change is fine.)
=============== Diff ===============
BasicClassOrganizer>>categoryForTestCases {*SUnitTools-accessing} · jr 3/5/2020 22:07 + categoryForTestCases + ^ self categories + detect: [:each | each beginsWith: 'test'] + ifNone: [Categorizer allCategory]
Browser>>newClassContents {accessing} · ct 1/16/2022 20:57 (changed) newClassContents - | theClassName | - ^ (theClassName := self selectedClassName) - ifNil: - [Class template: self selectedSystemCategory] - ifNotNil: - [Class templateForSubclassOf: theClassName asString category: self selectedSystemCategory] + + ^ self selectedClass + ifNil: [Class template: self selectedSystemCategory] + ifNotNil: [:theClass | theClass templateForSubclassInCategory: self selectedSystemCategory]
Class class>>template: {instance creation} · ct 1/16/2022 21:19 (changed) - template: aSystemCategoryName + template: systemCategoryName "Answer an expression that can be edited and evaluated in order to define a new class."
- ^ self templateForSubclassOf: Object name category: aSystemCategoryName + ^ Object templateForSubclassInCategory: systemCategoryName
Class class>>templateForSubclassOf:category: {instance creation} · ct 1/16/2022 20:58 (changed) templateForSubclassOf: priorClassName category: systemCategoryName "Answer an expression that can be edited and evaluated in order to define a new class, given that the class previously looked at was as given"
+ self deprecated: 'ct: Use Class >> #templateForSubclassInCategory:'. ^priorClassName asString, ' subclass: #NameOfSubclass instanceVariableNames: '''' classVariableNames: '''' poolDictionaries: '''' category: ''' , systemCategoryName asString , ''''
Class>>templateForSubclassInCategory: {subclass creation} · ct 1/16/2022 21:19 + templateForSubclassInCategory: categoryName + "Answer an expression that can be edited and evaluated in order to define a new class." + + ^ self + templateForSubclassNamed: #NameOfSubclass + category: categoryName
Class>>templateForSubclassNamed:category: {subclass creation} · ct 1/16/2022 21:19 + templateForSubclassNamed: subclassName category: categoryName + "Answer an expression that can be edited and evaluated in order to define a new class." + + ^ '<1p> subclass: <2p> + instanceVariableNames: '''' + classVariableNames: '''' + poolDictionaries: '''' + category: <3p>' expandMacrosWithArguments: + {self. subclassName asSymbol. categoryName}
CodeHolder>>testBrowseClassNamed:possibleMessageNamed: {*SUnitTools-running} · ct 1/16/2022 21:15 (changed) testBrowseClassNamed: aClassName possibleMessageNamed: aMessageName | cls selector | - (self class environment hasClassNamed: aClassName) ifFalse: ["no dice" ^ self]. + (self class environment hasClassNamed: aClassName) + ifFalse: [^ false]. cls := self class environment classNamed: aClassName.
(aMessageName notNil and: [cls includesLocalSelector: (selector := aMessageName asSymbol)]) ifTrue: [ToolSet browse: cls selector: selector] - ifFalse: [ToolSet browseClass: cls]. + ifFalse: [ToolSet browseClass: cls category: + cls organization categoryForTestCases]. + + ^ true
CodeHolder>>testFindTest {*SUnitTools-running} · ct 1/16/2022 21:21 (changed) testFindTest | cls destClassName destMessage | cls := self selectedClass ifNil: [^ self]. destClassName := cls name asString, 'Test'. destMessage := self selectedMessageName ifNotNil: [:name | self testSelectorFrom: name]. - self testBrowseClassNamed: destClassName possibleMessageNamed: destMessage + + (self testBrowseClassNamed: destClassName possibleMessageNamed: destMessage) + ifTrue: [^ self]. + (Project uiManager + chooseFromLabeledValues: (OrderedDictionary new + at: 'Create test case' translated put: [self testMakeTestCaseClassFor: destClassName]; + at: 'Cancel' translated put: []; + yourself) + title: ('There is no test for {1}' translated + format: {self selectedMessageName ifNil: [cls]})) value.
CodeHolder>>testMakeTestCaseClassFor: {*SUnitTools-running} · ct 1/16/2022 21:21 + testMakeTestCaseClassFor: className + + | category template | + self selectedClassOrMetaClass ifNil: [^ self]. + self okToChange ifFalse: [^ self]. + + category := (self selectedClass category findTokens: $-) in: [:testedCategoryTokens | + ({testedCategoryTokens first , 'Tests'} , testedCategoryTokens allButFirst) + joinSeparatedBy: $-]. + template := TestCase + templateForSubclassNamed: className + category: category. + (Browser fullOnCategory: category) + editSelection: #newClass; + contentsChanged; + changed: #editString with: template.
Best, Christoph
--- Sent from Squeak Inbox Talk
On 2022-01-10T18:24:35+01:00, jakres+squeak@gmail.com wrote:
Since there are so many different combinations you can probably make this arbitrarily complex. Then 7/8 of the feature are the guessing of the category. The question is whether it is worth it.
You could search all registered packages that start with the same stem for subclasses of TestCase. That may introduce some unwanted dependency between trunk packages, so you may want to stick to categories rather than packages instead. You may program for the known patterns, so add your *Tests-* pattern to the list. Which one comes next? If there is no existing test category with the stem, which of the conventions do you choose?
Per KISS I would stick to just one convention, which can also be the one you mentioned rather than the one I implemented. Changing the category of the class afterwards should be easy enough.
<christoph.thiede at student.hpi.uni-potsdam.de> schrieb am Mo., 10. Jan. 2022, 18:02:
Hi Jakob,
while reviewing this patch, I noticed that the category heuristic does not work in all situations. For example, it classifies a newly created WideSymbolTest under Collections-Tests rather than CollectionTests-Text. Do you have an idea how to improve the heuristic (e.g., search for other test classes in the same package, ...)? :)
Best, Christoph
*Sent from **Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk*
On 2020-03-07T14:08:02+00:00, christoph.thiede at student.hpi.uni-potsdam.de wrote:
Ah, ok :-)
http://www.hpi.de/ ________________________________ Von: Squeak-dev <squeak-dev-bounces at lists.squeakfoundation.org> im
Auftrag von Jakob Reschke <forums.jakob at resfarm.de>
Gesendet: Samstag, 7. März 2020 14:57:12 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Inbox: SUnitTools-jr.5.mcz
Thiede, Christoph <Christoph.Thiede at student.hpi.uni-potsdam.de
<mailto:Christoph.Thiede at student.hpi.uni-potsdam.de>> schrieb am Sa., 7. März 2020, 14:31:
What is the reason to use ClassBuilder instead of
#subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:?
The ability to specify the target environment.
Hi Christoph,
Thank you. I only read the code in your email (not in the attached file) and did not try it out, but here are my remarks:
* It allows you to edit the class definition, but it does not create the 'tests' method category (see SUnitTools-jr.6.mcz in the Inbox). Personally, I prefer that it takes care of all the trivial steps, rather than giving me the full flexibility. * "There is no test for ..." is assumed, but may not be true if the test class simply has a different name... that's why I prefer "No test case found for ..." * I am wary of the changes to the class template string methods. Are they really necessary? Please plan to commit that separately (and not with a "Complements SUnitTools-..." commit message) if at all. * The tenor on the list regarding the use of #in: was to avoid it and rather use a temporary variable.
Kind regards, Jakob
Am So., 16. Jan. 2022 um 21:30 Uhr schrieb christoph.thiede@student.hpi.uni-potsdam.de:
Hi Jakob,
please find the attached changeset, which revises the changes, allows the user to edit the new test case definition before creating it, and uses the 'KernelTests-Objects' pattern for test category derivation which is known from most Trunk packages. No further heuristics for related class search are included. I also revised the logic for subclass templates in the Kernel package a bit. If you like it, I can merge it into the Trunk. :-)
(At a later point in time, we might want to create a hook in the ToolSet for creating a new subclass and also make use of it in Parser>>#defineClass:. But for now, I think the change is fine.)
=============== Diff ===============
BasicClassOrganizer>>categoryForTestCases {*SUnitTools-accessing} · jr 3/5/2020 22:07
- categoryForTestCases
^ self categories
detect: [:each | each beginsWith: 'test']
ifNone: [Categorizer allCategory]
Browser>>newClassContents {accessing} · ct 1/16/2022 20:57 (changed) newClassContents
| theClassName |
^ (theClassName := self selectedClassName)
ifNil:
[Class template: self selectedSystemCategory]
ifNotNil:
[Class templateForSubclassOf: theClassName asString category: self selectedSystemCategory]
^ self selectedClass
ifNil: [Class template: self selectedSystemCategory]
ifNotNil: [:theClass | theClass templateForSubclassInCategory: self selectedSystemCategory]
Class class>>template: {instance creation} · ct 1/16/2022 21:19 (changed)
- template: aSystemCategoryName
- template: systemCategoryName "Answer an expression that can be edited and evaluated in order to define a new class."
^ self templateForSubclassOf: Object name category: aSystemCategoryName
^ Object templateForSubclassInCategory: systemCategoryName
Class class>>templateForSubclassOf:category: {instance creation} · ct 1/16/2022 20:58 (changed) templateForSubclassOf: priorClassName category: systemCategoryName "Answer an expression that can be edited and evaluated in order to define a new class, given that the class previously looked at was as given"
^priorClassName asString, ' subclass: #NameOfSubclass instanceVariableNames: '''' classVariableNames: '''' poolDictionaries: '''' category: ''' , systemCategoryName asString , ''''self deprecated: 'ct: Use Class >> #templateForSubclassInCategory:'.
Class>>templateForSubclassInCategory: {subclass creation} · ct 1/16/2022 21:19
- templateForSubclassInCategory: categoryName
"Answer an expression that can be edited and evaluated in order to define a new class."
^ self
templateForSubclassNamed: #NameOfSubclass
category: categoryName
Class>>templateForSubclassNamed:category: {subclass creation} · ct 1/16/2022 21:19
- templateForSubclassNamed: subclassName category: categoryName
"Answer an expression that can be edited and evaluated in order to define a new class."
^ '<1p> subclass: <2p>
instanceVariableNames: ''''
classVariableNames: ''''
poolDictionaries: ''''
category: <3p>' expandMacrosWithArguments:
{self. subclassName asSymbol. categoryName}
CodeHolder>>testBrowseClassNamed:possibleMessageNamed: {*SUnitTools-running} · ct 1/16/2022 21:15 (changed) testBrowseClassNamed: aClassName possibleMessageNamed: aMessageName
| cls selector |
(self class environment hasClassNamed: aClassName) ifFalse: ["no dice" ^ self].
(self class environment hasClassNamed: aClassName)
ifFalse: [^ false].
cls := self class environment classNamed: aClassName.
(aMessageName notNil and: [cls includesLocalSelector: (selector := aMessageName asSymbol)]) ifTrue: [ToolSet browse: cls selector: selector]
ifFalse: [ToolSet browseClass: cls].
ifFalse: [ToolSet browseClass: cls category:
cls organization categoryForTestCases].
^ true
CodeHolder>>testFindTest {*SUnitTools-running} · ct 1/16/2022 21:21 (changed) testFindTest | cls destClassName destMessage | cls := self selectedClass ifNil: [^ self]. destClassName := cls name asString, 'Test'. destMessage := self selectedMessageName ifNotNil: [:name | self testSelectorFrom: name].
self testBrowseClassNamed: destClassName possibleMessageNamed: destMessage
(self testBrowseClassNamed: destClassName possibleMessageNamed: destMessage)
ifTrue: [^ self].
(Project uiManager
chooseFromLabeledValues: (OrderedDictionary new
at: 'Create test case' translated put: [self testMakeTestCaseClassFor: destClassName];
at: 'Cancel' translated put: [];
yourself)
title: ('There is no test for {1}' translated
format: {self selectedMessageName ifNil: [cls]})) value.
CodeHolder>>testMakeTestCaseClassFor: {*SUnitTools-running} · ct 1/16/2022 21:21
- testMakeTestCaseClassFor: className
| category template |
self selectedClassOrMetaClass ifNil: [^ self].
self okToChange ifFalse: [^ self].
category := (self selectedClass category findTokens: $-) in: [:testedCategoryTokens |
({testedCategoryTokens first , 'Tests'} , testedCategoryTokens allButFirst)
joinSeparatedBy: $-].
template := TestCase
templateForSubclassNamed: className
category: category.
(Browser fullOnCategory: category)
editSelection: #newClass;
contentsChanged;
changed: #editString with: template.
Best, Christoph
Sent from Squeak Inbox Talk
On 2022-01-10T18:24:35+01:00, jakres+squeak@gmail.com wrote:
Since there are so many different combinations you can probably make this arbitrarily complex. Then 7/8 of the feature are the guessing of the category. The question is whether it is worth it.
You could search all registered packages that start with the same stem for subclasses of TestCase. That may introduce some unwanted dependency between trunk packages, so you may want to stick to categories rather than packages instead. You may program for the known patterns, so add your *Tests-* pattern to the list. Which one comes next? If there is no existing test category with the stem, which of the conventions do you choose?
Per KISS I would stick to just one convention, which can also be the one you mentioned rather than the one I implemented. Changing the category of the class afterwards should be easy enough.
<christoph.thiede at student.hpi.uni-potsdam.de> schrieb am Mo., 10. Jan. 2022, 18:02:
Hi Jakob,
while reviewing this patch, I noticed that the category heuristic does not work in all situations. For example, it classifies a newly created WideSymbolTest under Collections-Tests rather than CollectionTests-Text. Do you have an idea how to improve the heuristic (e.g., search for other test classes in the same package, ...)? :)
Best, Christoph
*Sent from **Squeak Inbox Talk https://github.com/hpi-swa-lab/squeak-inbox-talk*
On 2020-03-07T14:08:02+00:00, christoph.thiede at student.hpi.uni-potsdam.de wrote:
Ah, ok :-)
http://www.hpi.de/ ________________________________ Von: Squeak-dev <squeak-dev-bounces at lists.squeakfoundation.org> im
Auftrag von Jakob Reschke <forums.jakob at resfarm.de>
Gesendet: Samstag, 7. März 2020 14:57:12 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Inbox: SUnitTools-jr.5.mcz
Thiede, Christoph <Christoph.Thiede at student.hpi.uni-potsdam.de
<mailto:Christoph.Thiede at student.hpi.uni-potsdam.de>> schrieb am Sa., 7. März 2020, 14:31:
What is the reason to use ClassBuilder instead of
#subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:?
The ability to specify the target environment.
squeak-dev@lists.squeakfoundation.org