Spy is a flexible and open framework for designing and implementing program monitor. Spy enables easy-to-realize analysis.
The source code may be browsed online and downloaded from http://www.squeaksource.com/Spy.html. To install Spy, just evaluate the following in a Workspace:
(Smalltalk at: #ConfigurationOfSpy) project lastVersion load
Spy enables one to easily write a code profiler. When coupled with Mondrian, profiled information may be easily graphically rendered.
For example, a very primitive test coverage tool could be defined as:
MethodSpy subclass: #DemoTestCoverageMethodSpy
instanceVariableNames: 'nbOfExecutions testMethodsThatRunMe'
nbOfExecutions := 0.
testMethodsThatRunMe := Set new.
DemoTestCoverageMethodSpy>>beforeRun: methodName with: listOfArguments in: receiver
nbOfExecutions := nbOfExecutions + 1.
testMethodsThatRunMe add: self profiler class currentTestMethod
The code above create a subclass of MethodSpy, a kind of wrapper for methods. Each time a method on which this wrapper is installed will invoke the method beforeRun:with:in: before. Other hooks are available in MethodSpy.
You then need to create a spy for classes and packages:
ClassSpy subclass: #DemoTestCoverageClassSpy
"The following methods are defined on the class side!"
PackageSpy subclass: #DemoTestCoveragePackageSpy
You then need to subclass the class Profiler:
Profiler subclass: #DemoTestCoverage
"Defined on the class side!"
You can simply invoke it with:
| profiler |
profiler := DemoTestCoverage runTestsForPackagesMatching: 'Roassal*'.
You can then perform simple queries such as:
The code above says that 650 methods in Roassal are not executed when running Mondrian tests. The total amount of methods is(profiler allMethods select: [ :m | m nbOfExecutions = 0]) size
profiler allMethods size
The result is the three methods that are the most executed by different test methods.(profiler allMethods asSortedCollection:
[:m1 :m2 | m1 testMethodsThatRunMe size > m2 testMethodsThatRunMe size ]) copyFrom: 1 to: 3
=> a SortedCollection(<ROObject>>initialize> <RONullShape>>extent:> <RONullShape>>initialize>)
The profiling information obtained above become significant when being visualized. The Roassal agile visualization engine is used for this.
A visualization can be implemented by overriding #visualizeOn: in the package spy class:
view nodes: self allClasses forEach: [:each |
view shape rectangle
linearFillColor: [ :m | ((m nbOfExecutions + 1) log * 10) asInteger ] within: self allMethods.
view nodes: (each methods sortedAs: #nbOfExecutions).
view gridLayout gapSize: 2.
view edgesFrom: #superclass.
The visualization is obtained by executing:
The visualization obtained is exemplified:
Large squares are classes. Edges represent superclass links (above is a superclass of below). Inner classes are methods. The color tells about its number of execution: white methods are the one not covered by the unit tests, and the dark one are the methods executed many times.
Information about the principal author of Spy may be found on http://www.bergel.eu
South America, and especially Chile, has a strong link with Polynesia. Kai, Hapa’o and Keri are three words in Rapanui, the native language (still) spoken in Easter Island.