Bugspots in Python

What is bugspots in Python?

Bugspots is a Python implementation of the bug prediction algorithm used at Google. It also embed command-line interface which can be used to list the “hot spots” of a Git repository.

Google declares the top 10% of ranked files as hot-spots. During reviews and audits the developers can use this information to spend more time on them.

What is a hot spot?

A hot spot is merely a file that is bug-prone.

Installation

pip install bugspots

Algorithm

The algorithm looks through a list of commits and for every commit it checks if it is a bug-fix or not, which is not easy and an own research problem. If so, it then proceeds to increase the involved files’ scores depending on the commit’s age. Finally it returns a list of all files ranked based on the score they received:

for commit in commits_to_crawl:
    if commit_is_fix(commit):
        for file in commit.diff:
            file.score +=
                1 / (1 + math.exp(
                    (-12 * normalized_timestamp(commit)) + 12))

How does it work?

The algorithm is very simple and to the point: it gives each file a score based on its number of bug-fixing commits and their age, and then return a descending-ordered list of the files based on their score, filtering commits that are no longer at HEAD.

What is a bug-fixing commit?

Any commit whose purpose is to fix an issue. They are identified by message, using the same pattern as GitHub, which is:

(?i)(fix(e[sd])?|close[sd]?) #[1-9][0-9]*

Google determines if a commit fixed a bug by checking the commit message for an attached bug and then using their bug-tracking database to decide if it was a bug or a feature request. Existing open source implementations of the Bugspots algorithm use a regular expression (regex) on the commit messages to find indicators for bug-fixes, which is what the algorithm proposed in this thesis also uses.

What is the formula used?

The reasoning behind the weighting of commits is that without it, a buggy file that gets fixed still retains a high score. To account for fixed files, older bug-fixes weigh less than newer ones. Google proposed the following function as a way to weigh commits by age.

“Where n is the number of bug-fixing commits, and ti is the timestamp of the bug-fixing commit represented by i. The timestamp used in the equation is normalized from 0 to 1, where 0 is the earliest point in the code base, and 1 is now (where now is when the algorithm was run). Note that the score changes over time with this algorithm due to the moving normalization; it’s not meant to provide some objective score, only provide a means of comparison between one file and another at any one point in time.”

Command Line Usage

bugspots.py -h

Average Line-Score

The average line-score is a file score where we compute the average score overall lines in a file. Formally, let f be a file with n lines of code li, then:

The average line-score is a simple and thus easy to use approach but it may not yield a useful metric if large files that have a lot of untouched code and a small portion of highly bug prone code are part of bug-fixes. Those files could have a low score even if a significant amount of bug-fixes was applied to them.

Example

import bugspots
b = bugspots.Bugspots()
for hotspot in b.get_hotspots():
    print " %6.3f %s" % (hotspot.score, hotspot.filename)