Skip to content

Commit

Permalink
Removing dependency from ParameterizedTestCase for simplicity.
Browse files Browse the repository at this point in the history
  • Loading branch information
vitormcruz committed May 24, 2024
1 parent 305da38 commit db59093
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 204 deletions.
12 changes: 0 additions & 12 deletions pharo/Tome-Core/ManifestTomeCore.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,6 @@ Class {
#category : #'Tome-Core-Manifest'
}

{ #category : #'code-critics' }
ManifestTomeCore class >> ruleBadMessageRule2V1FalsePositive [

<ignoreForCoverage>
^ #(#(#(#RGMethodDefinition #(#'TomeFeature class' #protoParametersFor: #true)) #'2024-02-27T14:04:29.583-03:00') #(#(#RGMethodDefinition #(#TomeScenarioBuilderProtoParameter #convertInScenarioFor: #false)) #'2024-02-27T14:38:14.882-03:00') )
]

{ #category : #'code-critics' }
ManifestTomeCore class >> ruleCollectSelectNotUsedRuleV1FalsePositive [
^ #(#(#(#RGMethodDefinition #(#'TomeFeature class' #calculateProtoParameters #true)) #'2021-10-08T09:51:12.573064-03:00') )
]

{ #category : #'code-critics' }
ManifestTomeCore class >> ruleGRAnsiConvertorRuleV1FalsePositive [

Expand Down
5 changes: 5 additions & 0 deletions pharo/Tome-Core/TomeExampleTable.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ TomeExampleTable >> collect: aBlockClosure [
^ examples collect: aBlockClosure .
]

{ #category : #enumerating }
TomeExampleTable >> collectWithIndex: aBlockClosure [
^ examples collectWithIndex: aBlockClosure .
]

{ #category : #initialization }
TomeExampleTable >> initialize [

Expand Down
168 changes: 75 additions & 93 deletions pharo/Tome-Core/TomeFeature.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,20 @@ TO DO
"
Class {
#name : #TomeFeature,
#superclass : #ParametrizedTestCase,
#superclass : #TestCase,
#instVars : [
'concreteScenario'
'scenarioToRun'
],
#classVars : [
'VIRTUAL_SCENARIO_INDEX_SEPARATOR'
],
#category : #'Tome-Core'
}

{ #category : #'building suites' }
TomeFeature class >> calculateProtoParameters [
{ #category : #documentation }
TomeFeature class >> buildMicroDownUsing: aBuilder withComment: aString [

^ self scenarioPragmedMethods
inject: OrderedCollection new
into: [ :parameters :scenarioBuilderMethod |
parameters addAll: (self protoParametersFor: scenarioBuilderMethod selector);
yourself
]
Class buildMicroDownUsing: aBuilder withComment: aString
]

{ #category : #infos }
Expand All @@ -88,10 +86,16 @@ TomeFeature class >> featureName [
^ self name.
]

{ #category : #'class initialization' }
TomeFeature class >> initialize [

VIRTUAL_SCENARIO_INDEX_SEPARATOR := '__index__'.
]

{ #category : #private }
TomeFeature class >> isAbstract [

^ self name = #TomeFeature
^ self name = #TomeFeature.
]

{ #category : #infos }
Expand All @@ -100,129 +104,107 @@ TomeFeature class >> isFeature [
^ true.
]

{ #category : #'building suites' }
TomeFeature class >> protoParametersFor: scenarioBuilderMethodSelector [

" Return a list of TomeScenarioBuilderProtoParameter that can be used latter to create actual TomeScenario's."

| qtdScenarios |

qtdScenarios := (self new perform: scenarioBuilderMethodSelector) size.
^ (1 to: qtdScenarios)
collect: [ :exampleIndex |
TomeScenarioBuilderProtoParameter newForScenarioBuilderMethodName: scenarioBuilderMethodSelector
andExampleIndex: exampleIndex
].
]

{ #category : #'building suites' }
TomeFeature class >> scenarioPragmedMethods [

^ self methods select: [ :method | (method pragmas collect: #selector) includes: 'scenario' ]
]

{ #category : #'building suites' }
TomeFeature class >> testParameters [

"Parameters used to create multiple tests. In Tome, each test is a concrete scenario created by 'Builder' methods defined
in the instance side of the Feature Test class, each of which is annotated with a <scenario> pragma.
Also, for Tome, the test parameters are actually proto parameters, because they will be used later, when instances of test
case are created, to generate concrete test parameters used to create concrete scenarios, see `TomeScenarioBuilderProtoParameter`
for details. This is necessary because one of the actual parameters is a block clojure that must enclose the test case instance
context to work properly and, for example, be able to access prepared instance variables of the test case."

| protoParameters |

protoParameters := self calculateProtoParameters.
protoParameters ifEmpty: [ Error signal: 'No scenarios found. The feature classe must have at least one method annotated with the <senario> pragma' ].

^ protoParameters inject: ParametrizedTestMatrix new
into: [ :testMatrix :protoParameter | testMatrix addCase: {#concreteScenario -> protoParameter} ]
]

{ #category : #accessing }
TomeFeature >> concreteScenario [
TomeFeature class >> testSelectors [

<TODO: 'make testes validating this method'>
| instanceOfMe |

instanceOfMe := self new.

^ (self scenarioPragmedMethods collect: [ :scenarioMethod |
| qtdScenarios |

qtdScenarios := (scenarioMethod valueWithReceiver: instanceOfMe arguments: #()) size.
(1 to: qtdScenarios) collect: [ :index | scenarioMethod selector, VIRTUAL_SCENARIO_INDEX_SEPARATOR , index asString ]
]) flattened.

^ concreteScenario ifNil: [ (parametersToUse at: 1) valuable ].
]

{ #category : #accessing }
TomeFeature >> concreteScenario: anObject [
{ #category : #'reflective operations' }
TomeFeature >> doesNotUnderstand: aMessage [

concreteScenario := anObject
"Features Scenarios are Virtual Tests, i.e., methods are created dynamically dependending on the
scenarios definition — they actually do not exists. The testSelector selector defines the name of
the message for the virtual scenario, and scenarioToRun stores the sceario itself, then the DNU is
just used to dynamically link the message resolve to the scenario running — for a TestCase point
of view, it works just as expected."

(aMessage selector ~= testSelector) ifTrue: [ super doesNotUnderstand: aMessage ].
scenarioToRun run.
]

{ #category : #accessing }
TomeFeature >> parametersToUse: aCase [

"Convert ProtoParameter into actual TomeScenario parameter used by this concrete test case to
run the scenario. This guarantees that the execution block closure of the scenario encloses
correctly the context of this test case. "

| m |

m := (aCase at: 1).
m valuable: (m valuable convertInScenarioFor: self).

parametersToUse := aCase.
{ #category : #private }
TomeFeature >> instanceVariablesToKeep [
^ super instanceVariablesToKeep , #('scenarioToRun')
]

{ #category : #printing }
TomeFeature >> printOn: aStream [

parametersToUse ifNotNil: [
(parametersToUse collect: #valuable) printOn: aStream delimiter: $
]
scenarioToRun printOn: aStream.
]

{ #category : #'scenario builder' }
TomeFeature >> scenario: aString def: aStringDefinition run: aBlock [

^ {TomeScenario withName: aString
<TODO: 'test the case where a scenario was already created.'>

^ { [ TomeScenario withName: aString
definition: aStringDefinition
executionBlock: aBlock}
executionBlock: aBlock ] }

]

{ #category : #'scenario builder' }
TomeFeature >> scenarioDerivedFromSelector: aMessageSelector [

<TODO: 'Add tests for this method'>
| splitedMessage scenarioBuilderMethod scenarios scenarioIndex |

splitedMessage := aMessageSelector splitOn: VIRTUAL_SCENARIO_INDEX_SEPARATOR.
splitedMessage size ~= 2 ifTrue: [ Error signal: 'Cannot find the scenario with the povided selector' ].

scenarioBuilderMethod := self class compiledMethodAt: (splitedMessage at: 1) asSymbol.
scenarios := scenarioBuilderMethod valueWithReceiver: self arguments: #( ).

scenarioIndex := (splitedMessage at: 2) asNumber.
^ (scenarios at: scenarioIndex) value
]

{ #category : #'scenario builder' }
TomeFeature >> scenarioOutline: aString def: aStringDescription examples: examples run: aBlock [

^ (examples collect: [ :example |
self scenario: aString
(self scenario: aString
def: (example applyAsExampleTo: aStringDescription)
run: aBlock
run: aBlock)
]) flattened.
]

{ #category : #running }
TomeFeature >> setUp [
<deprecated: 'Fix for parametrized tests. Wait until fix in the image.'>

self initialize.
self parametersToUse do: [ :aParameter | aParameter applyTo: self ].

"If I am executed without calling buildSuite in the class. I will use the first set of options.
This is a workaround to work when running from Calypso"
(self parametersToUse isEmpty and: [self class testParameters expandMatrix isNotEmpty])
ifTrue: [
self class
testParameters expandMatrix first
do: [ :aParameter | aParameter applyTo: self ] ]
]

{ #category : #'parameterized tests' }
TomeFeature >> testScenario [
{ #category : #accessing }
TomeFeature >> scenarioToRun [

^ concreteScenario run.
^ scenarioToRun.
]

{ #category : #private }
TomeFeature >> setTestSelector: aSymbol [

testSelector := aSymbol.
scenarioToRun := self scenarioDerivedFromSelector: aSymbol
]

{ #category : #running }
{ #category : #'scenario builder' }
TomeFeature >> when: aBlock [

"Returns a WhenClause created in the context of the concreteScenario (TomeScenario) execution"
"Returns a WhenClause created in the context of the scenarioToRun (TomeScenario) execution"

^ concreteScenario when: aBlock.
^ scenarioToRun when: aBlock.
]
2 changes: 0 additions & 2 deletions pharo/Tome-Core/TomeParamFeatureAssertion.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,6 @@ TomeParamFeatureAssertion >> assertionError [

{ #category : #printing }
TomeParamFeatureAssertion >> printOn: aStream [
"Append to the argument, aStream, a sequence of characters that
identifies the receiver."

stringParam printOn: aStream.
]
Expand Down
40 changes: 14 additions & 26 deletions pharo/Tome-Core/TomeScenario.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ Class {
'name',
'definition',
'parameters',
'executionBlock',
'whenClauses'
'whenClauses',
'runBlock'
],
#category : #'Tome-Core'
}
Expand All @@ -26,7 +26,7 @@ TomeScenario class >> withName: scenarioName definition: scenarioDef executionBl
^ self new
name: scenarioName;
definition: scenarioDef;
executionBlock: aBlock.
runBlock: aBlock.
]

{ #category : #accessing }
Expand All @@ -40,16 +40,6 @@ TomeScenario >> definition: anObject [
definition := anObject ifNotNil: [ anObject withBlanksCondensed ].
]

{ #category : #accessing }
TomeScenario >> executionBlock [
^ executionBlock
]

{ #category : #accessing }
TomeScenario >> executionBlock: anObject [
executionBlock := anObject
]

{ #category : #running }
TomeScenario >> extractParameters [

Expand Down Expand Up @@ -96,18 +86,6 @@ TomeScenario >> parameters [
^ parameters clone.
]

{ #category : #converting }
TomeScenario >> parseBlockClosure: aBlockClosure [

| blockSource blockSourceLines |

blockSource := aBlockClosure asString.
blockSourceLines := {' run: ', blockSource lines first},
(blockSource lines allButFirst collect: [ :it | ' ', it ]).

^ (Character cr join: blockSourceLines), '<n>'.
]

{ #category : #printing }
TomeScenario >> printOn: aStream [
"Append to the argument, aStream, a sequence of characters that
Expand All @@ -128,7 +106,7 @@ TomeScenario >> run [
self validateScenario.

parameters := self extractParameters.
executionBlock valueWithPossibleArgs: parameters.
runBlock valueWithPossibleArgs: parameters.
whenClauses do: [ :whenClause | whenClause execute ].

parameters do: [ :param |
Expand All @@ -139,6 +117,16 @@ TomeScenario >> run [

]

{ #category : #accessing }
TomeScenario >> runBlock [
^ runBlock
]

{ #category : #accessing }
TomeScenario >> runBlock: aBlock [
runBlock := aBlock
]

{ #category : #converting }
TomeScenario >> scenarioDescription [

Expand Down
35 changes: 0 additions & 35 deletions pharo/Tome-Core/TomeScenarioBuilderProtoParameter.class.st

This file was deleted.

Loading

0 comments on commit db59093

Please sign in to comment.