Creating Custom DGML Diagrams using the Progression API

*Moved to: http://fluentbytes.com/creating-custom-dgml-diagrams-using-the-progression-api/

Thursday night I presented a Session for the VSUG in Belgium, with the title “Modeling that works with code”. In this session I demonstrated how we can add more value into models and diagrams and how that can help us to keep our model in sync with the actual codebase we work on. (You can download the presentation here)

During this session I also addressed the concept of creating your own custom DGML diagram, using the progression API, that can be found in the visual studio directories.

In this post I want to describe how you can create a Custom DGML diagram. I will show you how you can use the standard Coverage files you get from the Microsoft Test tools and use that data to create a diagram that shows which classes have a coverage percentage below a defined quality bar.

When you want to create a DGML diagram, you can do that by using the Progression API. You can find the classes you need in the following assemblies :

  • Microsoft.VisualStudio.Progression.Common
  • Microsoft.VisualStudio.Progression.GraphModel

Just use the add reference dialog and browse to the following location:
<installdrive>:Program Filesvisual Studio 10Common7IdePrivateAssemblies

note:on a 64 bit machine this is program Files (x86) instead of program files

I want to create a new diagram, so to start, I need an instance of a Graph object. This is nothing more than just creating an instance of the Graph class. Now I want to define some custom metadata to my Nodes, that contain the code coverage information. For that purpose, I register a custom metadata property of the type double with the name “CodeCoverage” and I register it to be available on the Nodes in my diagram.

So the only thing I need to do is load the Code Coverage XML file, use an XLinq query to get only the Class nodes and then create a loop that generates the nodes I want to add to the diagram.

The code for this is like follows:

Graph DgmlGraph = Graph.Load(filetoAnnotate);
GraphProperty codeCoverageProperty =
GraphProperty.Register("CodeCoverage", typeof(double),
GraphMetadata.Default, typeof(Node));
var codeCoverageXmlFile = XElement.Load(coverageFileName);
foreach (var classCoverageNode in codeCoverageXmlFile.Descendants("Class"))
{
    var classname = classCoverageNode.Element("ClassName").Value;
    int linesCovered = int.Parse(classCoverageNode.Element("LinesCovered").Value);
    int linesNotCovered = int.Parse(classCoverageNode.Element("LinesNotCovered").Value);
    int linesPartiallyCovered =
        int.Parse(classCoverageNode.Element("LinesPartiallyCovered").Value);
    int totalLines = linesCovered + linesNotCovered + linesPartiallyCovered;
    double coveragePercentage = (linesCovered * 100 / totalLines);
    Node coverageNode = new Node(className);
    coverageNode.SetValue<double>(codeCoverageProperty, coveragePercentage);
    DgmlGraph.Nodes.Add(coverageNode);
}

So now I have a Graph, that contains nodes and each node has the percentage code coverage set.

Finally, I need to define specific styles so the diagram shows which classes are below a certain code coverage percentage and which are above. For that you can add so called Conditional Styles to the diagram. This is also very straightforward to do.

You just create a new ConditionalStyle object instance and give it the graph as argument. Then you define to what type of element it needs to be applied to in the DGML diagram. So for this purpose we define this style to be applied to the “Node “ type. Next you give it a Label and last but not least a Condition. The expressions that evaluate if it needs to apply the condition can use all information in the model. The expression syntax can be found here (http://msdn.microsoft.com/en-us/library/dd409453(VS.100).aspx#Highlight)

So for this diagram, I want to apply the style to all nodes with Code Coverage > 80. Therefore I need to apply the following expression: “CodeCoverage > 80”

var ConditionalStyle = new ConditionalStyle(DgmlGraph);
ConditionalStyle.TargetType = typeof(Node);
ConditionalStyle.GroupLabel = "Coverage > 80%";
var Condition = new Condition(ConditionalStyle);
Condition.Expression = "CodeCoverage > 80";
ConditionalStyle.Conditions.Add(Condition);
DgmlGraph.Styles.Add(ConditionalStyle);

Now the last thing I need to do is define what property of a node visualization I want to change on this ConditionalStyle. I choose to set an Icon to be a green checkmark and the background to green

var CodeCoverageSetterBackGround = new Setter(ConditionalStyle, “BackGround”);

CodeCoverageSetterBackGround.Value = “#FF00FF00”;

ConditionalStyle.Setters.Add(CodeCoverageSetterBackGround);

var CodeCoverageSetterIcon = new Setter(ConditionalStyle, “Icon”);

CodeCoverageSetterIcon.Value = “pack://application:,,,/Microsoft.VisualStudio.Progression.GraphControl;component/Icons/kpi_green_sym2_large.png”;

ConditionalStyle.Setters.Add(CodeCoverageSetterIcon);

I also did the same for coverage below 80% and set that style to be Red and use the Icon type “Node.Error”.

So now when I run my program with a code coverage file, I will get the following results:

clip_image002

In a next post, I will show you how you can also leverage the DGML diagrams generated with the architecture explorer and then applying this same code coverage information to that diagram, so you can decide which classed need additional effort in getting better coverage.

Cheers,

Marcel

Follow my new blog on http://fluentbytes.com