123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751 |
- Smalltalk createPackage: 'Helios-SUnit'!
- HLToolListWidget subclass: #HLMultiSelectToolListWidget
- slots: {}
- package: 'Helios-SUnit'!
- !HLMultiSelectToolListWidget commentStamp!
- This is a list that handles multiple selection!
- !HLMultiSelectToolListWidget methodsFor: 'accessing'!
- activeItemCssClass
- ^'selector'
- !
- listCssClass
- ^'nav nav-multiselect nav-pills nav-stacked'
- !
- listCssClassForItem: anObject
- ^(super listCssClassForItem: anObject), ((self isSelected: anObject)
- ifTrue: [' active']
- ifFalse: ['']).
- ! !
- !HLMultiSelectToolListWidget methodsFor: 'actions'!
- select: anObject
- self subclassResponsibility
- !
- toggleListItem: aListItem
- | item |
-
- (aListItem get: 0) ifNil: [ ^ self ].
- "Find item"
- item := aListItem data: 'item'.
- self toggleSelection: item
- !
- toggleSelection: anObject
- (self isSelected: anObject)
- ifTrue: [ self unselect: anObject ]
- ifFalse: [self select: anObject ]
- !
- unselect: anObject
- self subclassResponsibility
- ! !
- !HLMultiSelectToolListWidget methodsFor: 'rendering'!
- reselectItem: anObject
- anObject ifNil: [^self].
- self toggleSelection: anObject
- ! !
- !HLMultiSelectToolListWidget methodsFor: 'testing'!
- isSelected: anObject
- self subclassResponsibility
- ! !
- HLMultiSelectToolListWidget subclass: #HLSUnitClassesListWidget
- slots: {}
- package: 'Helios-SUnit'!
- !HLSUnitClassesListWidget commentStamp!
- I display a list of classes (subclasses of `TestCase`).!
- !HLSUnitClassesListWidget methodsFor: 'accessing'!
- buttonsDivCssClass
- ^ 'buttons_bar'
- !
- cssClassForItem: aClass
- | nonMeta |
- nonMeta := aClass theNonMetaClass.
- (nonMeta respondsTo: #classTag)
- ifTrue: [ ^ nonMeta classTag ]
- ifFalse: [ ^ nonMeta heliosClass ]
- !
- items
- ^ items ifNil: [ self initializeItems ]
- !
- label
- ^ 'Classes'
- ! !
- !HLSUnitClassesListWidget methodsFor: 'actions'!
- observeModel
- self model announcer
- on: HLPackageSelected
- send: #onPackageSelected:
- to: self;
-
- on: HLPackageUnselected
- send: #onPackageUnselected:
- to: self;
-
- on: HLClassSelected
- send: #onClassSelected:
- to: self;
-
- on: HLClassUnselected
- send: #onClassUnselected:
- to: self.
- !
- observeSystem
- self model systemAnnouncer
- on: ClassAdded
- send: #onClassAdded:
- to: self.
- !
- select: anObject
- model selectClass: anObject
- !
- unselect: anObject
- model unselectClass: anObject
- ! !
- !HLSUnitClassesListWidget methodsFor: 'initialization'!
- initializeItems
- ^items := model testClasses
- ! !
- !HLSUnitClassesListWidget methodsFor: 'reactions'!
- onClassAdded: anAnnouncement
- (self model selectedPackages includes: anAnnouncement theClass package)
- ifTrue: [
- self
- initializeItems;
- refresh ]
- !
- onClassSelected: anAnnouncement
- | listItem |
- listItem := self findListItemFor: anAnnouncement item.
- listItem addClass: 'active'.
- !
- onClassUnselected: anAnnouncement
- | listItem |
- listItem := self findListItemFor: anAnnouncement item.
- listItem removeClass: 'active'.
- !
- onPackageSelected: anAnnouncement
- self initializeItems;
- refresh
- !
- onPackageUnselected: anAnnouncement
- self initializeItems;
- refresh
- ! !
- !HLSUnitClassesListWidget methodsFor: 'rendering'!
- renderButtonsOn: html
- html button
- class: 'button';
- with: 'Select all';
- onClick: [ self model selectAllClasses ]
- !
- renderItemLabel: aClass on: html
- html with: aClass name
- ! !
- !HLSUnitClassesListWidget methodsFor: 'testing'!
- isSelected: anObject
- ^model selectedClasses includes: anObject
- ! !
- HLMultiSelectToolListWidget subclass: #HLSUnitPackagesListWidget
- slots: {}
- package: 'Helios-SUnit'!
- !HLSUnitPackagesListWidget commentStamp!
- I display a list of packages for which unit tests are associated (packages containing subclasses of `TestCase`).!
- !HLSUnitPackagesListWidget methodsFor: 'accessing'!
- buttonsDivCssClass
- ^ 'buttons_bar'
- !
- cssClassForItem: anItem
- ^ anItem isDirty
- ifTrue: [ 'package_dirty' ]
- ifFalse: [ 'package' ]
- !
- items
- ^ items ifNil: [ self initializeItems ]
- !
- label
- ^ 'Packages'
- ! !
- !HLSUnitPackagesListWidget methodsFor: 'actions'!
- observeModel
- self model announcer
- on: HLPackageSelected
- send: #onPackageSelected:
- to: self;
-
- on: HLPackageUnselected
- send: #onPackageUnselected:
- to: self
- !
- observeSystem
- self model systemAnnouncer
- on: ClassAdded
- send: #onClassAdded:
- to: self.
- !
- select: anObject
- model selectPackage: anObject
- !
- unselect: anObject
- model unselectPackage: anObject
- ! !
- !HLSUnitPackagesListWidget methodsFor: 'initialization'!
- initializeItems
- ^items := model testPackages
- sort: [:a :b | a name < b name]
- ! !
- !HLSUnitPackagesListWidget methodsFor: 'reactions'!
- onClassAdded: anAnnouncement
- ((self items includes: anAnnouncement theClass package) not and: [anAnnouncement theClass package isTestPackage])
- ifTrue: [
- self
- initializeItems;
- refresh ]
- !
- onPackageSelected: anAnnouncement
- | listItem |
- listItem := self findListItemFor: anAnnouncement item.
- listItem addClass: 'active'.
- !
- onPackageUnselected: anAnnouncement
- | listItem |
- listItem := self findListItemFor: anAnnouncement item.
- listItem removeClass: 'active'.
- ! !
- !HLSUnitPackagesListWidget methodsFor: 'rendering'!
- renderButtonsOn: html
- html button
- class: 'button';
- with: 'Run Tests';
- onClick: [ self model runTests ].
- html button
- class: 'button';
- with: 'Select all';
- onClick: [ self model selectAllPackages ]
- !
- renderItemLabel: aPackage on: html
- html with: aPackage name
- ! !
- !HLSUnitPackagesListWidget methodsFor: 'testing'!
- isSelected: anObject
- ^model selectedPackages includes: anObject
- ! !
- HLWidget subclass: #HLSUnit
- slots: {#model. #packagesListWidget. #classesListWidget. #resultWidget. #failuresWidget. #errorsWidget}
- package: 'Helios-SUnit'!
- !HLSUnit commentStamp!
- I am the main widget for running unit tests in Helios.
- I provide the ability to select set of tests to run per package, and a detailed result log with passed tests, failed tests and errors.!
- !HLSUnit methodsFor: 'accessing'!
- model
- ^ model ifNil: [ model := HLSUnitModel new ]
- !
- resultSection
- ^HLHorizontalSplitter
- with: self resultWidget
- with: (HLHorizontalSplitter
- with: self failuresWidget
- with: self errorsWidget)
- ! !
- !HLSUnit methodsFor: 'actions'!
- unregister
- super unregister.
- {
- self packagesListWidget.
- self classesListWidget.
- self resultWidget.
- self errorsWidget.
- self failuresWidget
- }
- do: [ :each | each unregister ]
- ! !
- !HLSUnit methodsFor: 'keybindings'!
- registerBindingsOn: aBindingGroup
- HLToolCommand
- registerConcreteClassesOn: aBindingGroup
- for: self model
- ! !
- !HLSUnit methodsFor: 'rendering'!
- renderContentOn: html
- | resultSection |
- html with: (HLContainer with: (
- HLVerticalSplitter
- with: (HLVerticalSplitter
- with: self packagesListWidget
- with: self classesListWidget)
- with: (resultSection := self resultSection))).
-
- [resultSection resize: 0] valueWithTimeout: 100.
-
- self packagesListWidget focus
- ! !
- !HLSUnit methodsFor: 'widgets'!
- classesListWidget
- ^ classesListWidget ifNil: [
- classesListWidget := HLSUnitClassesListWidget on: self model.
- classesListWidget next: self failuresWidget ]
- !
- errorsWidget
- ^ errorsWidget ifNil: [errorsWidget := HLSUnitErrorsListWidget on: self model]
- !
- failuresWidget
- ^ failuresWidget ifNil: [
- failuresWidget := HLSUnitFailuresListWidget on: self model.
- failuresWidget next: self errorsWidget]
- !
- packagesListWidget
- ^ packagesListWidget ifNil: [
- packagesListWidget := HLSUnitPackagesListWidget on: self model.
- packagesListWidget next: self classesListWidget]
- !
- resultWidget
- ^ resultWidget ifNil: [
- resultWidget := HLSUnitResults new
- model: self model;
- yourself]
- ! !
- !HLSUnit class methodsFor: 'accessing'!
- tabClass
- ^ 'sunit'
- !
- tabLabel
- ^ 'SUnit'
- !
- tabPriority
- ^ 1000
- ! !
- !HLSUnit class methodsFor: 'testing'!
- canBeOpenAsTab
- ^ true
- ! !
- HLModel subclass: #HLSUnitModel
- slots: {#selectedPackages. #selectedClasses. #testResult. #currentSuite}
- package: 'Helios-SUnit'!
- !HLSUnitModel commentStamp!
- I am the model for running unit tests in Helios.
- I provide the ability to select set of tests to run per package, and a detailed result log with passed tests, failed tests and errors.!
- !HLSUnitModel methodsFor: 'accessing'!
- currentSuite
- ^currentSuite
- !
- selectedClasses
- ^ (self unfilteredSelectedClasses) select: [ :each |
- self selectedPackages includes: each package ]
- !
- selectedPackages
- ^ selectedPackages ifNil: [ selectedPackages := Set new ]
- !
- testCases
- | testCases |
- testCases := #().
- self selectedClasses
- do: [ :each | testCases addAll: each buildSuite ].
- ^ testCases
- !
- testClasses
- "Answer all concrete subclasses of TestCase in selected packages"
-
- | stream |
- stream := Array new writeStream.
- self selectedPackages do: [ :package |
- stream nextPutAll: (package classes select: [ :each |
- each isTestClass ] ) ].
- ^ stream contents
- !
- testPackages
- "Answer all packages containing concrete subclasses of TestCase"
-
- ^ self environment packages
- select: [ :each | each isTestPackage ]
- !
- testResult
- ^testResult ifNil: [testResult := TestResult new]
- ! !
- !HLSUnitModel methodsFor: 'actions'!
- invertSelectedClasses
- self testClasses do: [:each |
- (self unfilteredSelectedClasses includes: each)
- ifTrue: [ self unselectClass: each ]
- ifFalse: [ self selectClass: each ]].
- !
- invertSelectedPackages
- self testPackages do: [:each |
- (self selectedPackages includes: each)
- ifTrue: [ self unselectPackage: each ]
- ifFalse: [ self selectPackage: each ]].
- !
- runTests
- | worker |
- worker := (self environment classNamed: #TestSuiteRunner) on: self testCases.
- testResult := worker result.
- self announcer announce: (HLRunTests on: worker).
- self subscribeToTestSuite: worker.
- worker run
- !
- selectAllClasses
- self testClasses do: [:each | self selectClass: each].
- !
- selectAllPackages
- self testPackages do: [:each | self selectPackage: each].
- !
- selectClass: aClass
- self unfilteredSelectedClasses add: aClass.
- self announcer announce: (HLClassSelected on: aClass).
- !
- selectPackage: aPackage
- self selectedPackages add: aPackage.
- self announcer announce: (HLPackageSelected on: aPackage).
- !
- subscribeToTestSuite: aTestSuiteRunner
- currentSuite ifNotNil: [ currentSuite announcer unsubscribe: self].
- currentSuite := aTestSuiteRunner.
- currentSuite announcer
- on: ResultAnnouncement
- send: #onResultAnnouncement:
- to: self
- !
- unselectClass: aClass
- self unfilteredSelectedClasses remove: aClass ifAbsent: [^self].
- self announcer announce: (HLClassUnselected on: aClass).
- !
- unselectPackage: aPackage
- self selectedPackages remove: aPackage ifAbsent: [^self].
- self announcer announce: (HLPackageUnselected on: aPackage).
- ! !
- !HLSUnitModel methodsFor: 'private'!
- unfilteredSelectedClasses
- ^ (selectedClasses ifNil: [ selectedClasses := Set new ])
- ! !
- !HLSUnitModel methodsFor: 'reacting'!
- onResultAnnouncement: announcement
- "Propogate announcement"
- self announcer announce: announcement.
- ! !
- HLToolListWidget subclass: #HLSUnitResultListWidget
- slots: {}
- package: 'Helios-SUnit'!
- !HLSUnitResultListWidget commentStamp!
- I group the lists that display test results!
- !HLSUnitResultListWidget methodsFor: 'actions'!
- performFailure: aTestCase
- aTestCase debugCase
- ! !
- !HLSUnitResultListWidget methodsFor: 'initialization'!
- observeModel
- self model announcer
- on: ResultAnnouncement
- send: #onResultAnnouncement:
- to: self
- ! !
- !HLSUnitResultListWidget methodsFor: 'reacting'!
- onResultAnnouncement: announcement
- self refresh.
- ! !
- !HLSUnitResultListWidget methodsFor: 'rendering'!
- renderItemLabel: anObject on: html
- html with: anObject class name, ' >> ', anObject selector
- !
- reselectItem: anObject
- self performFailure: anObject
- ! !
- HLSUnitResultListWidget subclass: #HLSUnitErrorsListWidget
- slots: {}
- package: 'Helios-SUnit'!
- !HLSUnitErrorsListWidget commentStamp!
- I display a list of tests that have errors!
- !HLSUnitErrorsListWidget methodsFor: 'accessing'!
- items
- ^self model testResult errors
- !
- label
- ^'Errors'
- ! !
- HLSUnitResultListWidget subclass: #HLSUnitFailuresListWidget
- slots: {}
- package: 'Helios-SUnit'!
- !HLSUnitFailuresListWidget commentStamp!
- I display a list of tests that have failures!
- !HLSUnitFailuresListWidget methodsFor: 'accessing'!
- items
- ^self model testResult failures
- !
- label
- ^'Failures'
- ! !
- HLWidget subclass: #HLSUnitResultStatus
- slots: {#model}
- package: 'Helios-SUnit'!
- !HLSUnitResultStatus commentStamp!
- I display the status of the previous test run
- 1. How many tests where run.
- * How many tests passed.
- * How many tests failed.
- * How many tests resulted in an error.!
- !HLSUnitResultStatus methodsFor: 'accessing'!
- model
- ^ model ifNil: [model := TestResult new]
- !
- model: anObject
- model := anObject.
- self observeModel.
- !
- result
- ^ self model testResult
- !
- statusCssClass
- ^'sunit status ', self result status
- !
- statusInfo
- ^ self printTotal, self printPasses, self printErrors, self printFailures
- ! !
- !HLSUnitResultStatus methodsFor: 'actions'!
- observeModel
- self model announcer
- on: ResultAnnouncement
- send: #onResultAnnouncement:
- to: self
- !
- unregister
- super unregister.
- self model announcer unsubscribe: self.
- ! !
- !HLSUnitResultStatus methodsFor: 'printing'!
- printErrors
- ^ self result errors size asString , ' errors, '
- !
- printFailures
- ^ self result failures size asString, ' failures'
- !
- printPasses
- ^ (self result runs - self result errors size - self result failures size) asString , ' passes, '
- !
- printTotal
- ^ self result total asString, ' runs, '
- ! !
- !HLSUnitResultStatus methodsFor: 'reacting'!
- onResultAnnouncement: announcement
- self refresh.
- ! !
- !HLSUnitResultStatus methodsFor: 'rendering'!
- renderContentOn: html
- html div
- class: self statusCssClass;
- with: [ html span with: self statusInfo ]
- ! !
- HLWidget subclass: #HLSUnitResults
- slots: {#model. #progressBarWidget. #resultStatusWidget}
- package: 'Helios-SUnit'!
- !HLSUnitResults commentStamp!
- I am the widget that displays the test results for a previous test run in Helios.
- I display.
- 1. The status of the tests.
- * Progress of the currently running test suite.!
- !HLSUnitResults methodsFor: 'accessing'!
- model
- ^model
- !
- model: anObject
- model := anObject.
- self observeModel
- !
- progressBarWidget
- ^progressBarWidget ifNil: [progressBarWidget := HLProgressBarWidget new
- label: '';
- yourself]
- !
- resultStatusWidget
- ^resultStatusWidget ifNil: [resultStatusWidget := HLSUnitResultStatus new
- model: self model;
- yourself]
- ! !
- !HLSUnitResults methodsFor: 'actions'!
- unregister
- super unregister.
- self model announcer unsubscribe: self.
- self resultStatusWidget unregister.
- ! !
- !HLSUnitResults methodsFor: 'initialization'!
- observeModel
- self model announcer
- on: HLRunTests
- send: #onRunTests:
- to: self;
-
- on: ResultAnnouncement
- send: #onResultAnnouncement:
- to: self
- ! !
- !HLSUnitResults methodsFor: 'reacting'!
- onResultAnnouncement: announcement
- [self progressBarWidget
- updateProgress: (self model testResult runs / self model testResult total * 100) rounded] fork
- !
- onRunTests: announcement
- self progressBarWidget updateProgress: 0;
- refresh.
- ! !
- !HLSUnitResults methodsFor: 'rendering'!
- renderContentOn: html
- html with: self resultStatusWidget;
- with: self progressBarWidget
- ! !
|