{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Introduction\n", "In an upcoming analysis, we want to calculate the structural similarity between test cases. For this, we need the information which test methods call which code in the application (the \"production code\"). \n", "\n", "In this blog post, I'll show how you can get this information by using [jQAssistant](http://buschmais.github.io/jqassistant/doc/1.3.0/) for a Java application. With jQAssistant, you can scan the structural information of your software. I'll also explain the relevant database query that delivers the information we need later on." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Dataset\n", "\n", "I've scanned a small pet project of mine called \"DropOver\" that was originally developed as a web application for organizing parties or bar-hoppings. I've just added jQAssistant as a Maven plugin to my project's Maven build ([see here for a mini tutorial](https://github.com/JavaOnAutobahn/spring-petclinic/blob/master/readme.md)). The structures of this application are stored by jQAssistant in a property graph within the graph database [Neo4j](https://neo4j.com/). A subgraph with the structural information that's relevant for our purposes looks like this:\n", "\n", "![](../notebooks/resources/test_refactoring.png)\n", " \n", "We can see the scanned software entities like Java types (red) or methods (blue) as well their relationships with each other. We can now explore the database's content with the included Neo4j browser frontend or access the data with a programming language. I use Python (the programming language we'll write our analysis later on) with the `py2neo` module (the bridge between Python and Neo4j). The information we need can be retrieved by creating and executing a Cypher query (explained in the following) – Neo4j's language for accessing information in the property graph.\n", "\n", "Last, we store the results in a Pandas `DataFrame` named `invocations` for a nice tabular representation of the outputs and for further analysis." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " | test_type | \n", "test_method | \n", "prod_type | \n", "prod_method | \n", "invocations | \n", "
---|---|---|---|---|---|
0 | \n", "AddCommentTest | \n", "void blankSiteContainsRightComment() | \n", "AddComment | \n", "at.dropover.comment.boundary.GetCommentRespons... | \n", "1 | \n", "
1 | \n", "AddCommentTest | \n", "void blankSiteContainsRightCreationTime() | \n", "AddComment | \n", "at.dropover.comment.boundary.GetCommentRespons... | \n", "1 | \n", "
2 | \n", "AddCommentTest | \n", "void blankSiteContainsRightUser() | \n", "AddComment | \n", "at.dropover.comment.boundary.GetCommentRespons... | \n", "1 | \n", "
3 | \n", "AddCommentTest | \n", "void failsAtCommentNull() | \n", "AddComment | \n", "at.dropover.comment.boundary.GetCommentRespons... | \n", "1 | \n", "
4 | \n", "AddCommentTest | \n", "void failsAtCreatorNull() | \n", "AddComment | \n", "at.dropover.comment.boundary.GetCommentRespons... | \n", "1 | \n", "