Skip to content

Static analysis language-independent test coverage tool

License

Notifications You must be signed in to change notification settings

dxworks/spektrum

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Spektrum

A static, language-independent code analysis tool that generates test coverage metrics based on input generated from other external tools.

Running the Tool

In order to generate the coverage metric, grab the latest release of the tool from here, unzip the archive, navigate to the place where you extracted the contents in a terminal and run the following (you'll at least need Java 1.8 to run):

$ java -jar ./spektrum.jar [language] [input]

Where language is the language of the project (at the moment only java and cs are supported - for Java and C#) and input is the path to the input file.

In case you only want to try it out, there is a couple of sample input files in the ./sample-inputs directory. Here are some examples of how you'd run the tool with the sample inputs:

$ java -jar ./spektrum.jar cs ./sample-inputs/honeydew_cs.json # for C#
$ java -jar ./spektrum.jar java ./sample-inputs/insider_java.json # for Java

The Output

After running, the tool will generate a model.json file containing information about the model's coverage in the ./analytics directory. This file will contain a list of objects that have the following fields:

Field Type Short Description
identifier String The unique identifier of the object
type String The type of the object
coverage Float The test coverage % of the object (between 0.0 and 1.0)
testAmount Float The % of how much of the children are test units (between 0.0 and 1.0)
children List A recursive list that contains the children on the object

Identifier

The identifiers of the objects respect the following notation: [parent_identifier]->[object_identifier]. So if you'd have a class Foo that has a bar() method in it, the identifier of the object that corresponds to the method would be Foo->bar().

Type

The available types differ from one language to another. Here are the type hierarchies used for the currently supported languages:

  • C#: PROJECT > FILE > NAMESPACE > CLASS > METHOD
  • Java: PROJECT > PACKAGE > CLASS > METHOD

Visualizer

In case you want to see the output of the tool in a more human-readable way, you can use the visualizer tool, that you can access by opening ./visualizer/index.html in a browser.

After opening it, use the file picker to select the file that was generated by the tool and after that you'll be able to see your project's hierarchy in a tree view where you can search for certain entries and filter by the coverage and test amount percentage.

Custom Rules

A rule is a function that takes in one parameter that contains information about a unit and returns a boolean: true if the unit should be considered a test unit and false if the unit should be considered a testable unit.

The ./rules directory contains one subdirectory for each language that is supported by the tool. Each one of those subdirectories contains a rule.groovy file that has a check(unitInfo) function inside it. This function contains the logic that is used to determine whether a unit is a test unit or a testable unit.

If you feel like the default rules of this tool don't work well with your project, you have the option to write your own custom rules to identify which units should be considered test units. All you have to do to accomplish that is you have to replace the default logic from the check function with your own logic. That's it!

Example

Let's say you don't like the rule used for Java projects. All you'd have to do is you have to do to ./rules/java/rule.groovy's check function and replace its content with whatever you feel fits your project (more info about the unitInfo parameter will come in the next subsection).

package rules.java

def coolRuleA(unitInfo) {
    def isRespected = false

    // rule A logic...

    return isRespected
}

def coolRuleB(unitInfo) {
    def isRespected = false

    // rule B logic...

    return isRespected
}

def check(unitInfo) {
    return coolRuleA(unitInfo) || coolRuleB(unitInfo)
}

The unitInfo Parameter

The unitInfo parameter contains all the information that is available about a certain unit. This information differs from one language to the other:

  1. C#
Field Type Description
unitInfo.project.name String Name of the project in which the unit is
unitInfo.project.path String Path to the project in which the unit is
unitInfo.project.projectReferences Set<String> References to the project in which the unit is
unitInfo.project.externalReferences Set<String> References to other projects made by the project in which the unit is
unitInfo.file.name String Name of the file of the unit
unitInfo.file.path String Path to the file of the unit
unitInfo.namespace.name String Name of the unit's namespace
unitInfo.cls.name String Name if the unit's class
unitInfo.cls.type String Type of the unit's class
unitInfo.cls.usingStatements Set Using statements of the unit's class
unitInfo.cls.attributes Set Attributes of the unit's class
unitInfo.cls.usedClasses Set Classes used by unit's class
unitInfo.method.name String Name of the unit (format is <file>-><namespace>.<class>@<method>#<params>)
unitInfo.method.attributes Set<String> Attributes of the unit
unitInfo.method.modifiers Set<String> Modifiers of the unit
unitInfo.method.callers Set<String> Methods that call the unit (in the format from the TheOutput section)
unitInfo.method.calledMethods Set<String> Methods called by the unit (in the format from the TheOutput section)
unitInfo.method.type String Type of the unit
  1. Java
Field Type Description
unitInfo.project.name String Name of unit's project
unitInfo.pkg.name String Name of unit's package
unitInfo.cls.name String Name of unit's class
unitInfo.cls.dependencies Set Dependencies used in unit's class
unitInfo.method.signature String Unit's signature
unitInfo.method.callers Set Methods that call the unit
unitInfo.method.calledMethods Set Methods called by the unit