Over a million developers have joined DZone.

Test Your Dependencies With Degraph

· DevOps Zone

Discover how to optimize your DevOps workflows with our cloud-based automated testing infrastructure, brought to you in partnership with Sauce Labs

I wrote before about (anti)patterns in package dependencies. And of course the regular reader of my blog knows about Degraph, my private project to provide a visualization for package dependencies which can help a lot when you try to identify and fix such antipatterns.

But instead of fixing a problem we all probably prefer preventing the problem in the first place. Therefore in the latest version Degraph got a new feature: A DSL for testing Dependencies.

You can write tests either in Scala or in Java, whatever fits better into your project.

A typical test written with ScalaTest looks like this:

classpath // analyze everything found in the current classpath
.including("de.schauderhaft.**") // only the classes that start with "de.schauderhaft."
.withSlicing("module", "de.schauderhaft.(*).**") // use the third part of the package name as the module name, and make sure the modules don't have cycles
.withSlicing("layer",
("persistence","de.schauderhaft.legacy.db.**"), // consider everything in the package de.schauderhaft.legacy.db and subpackages as part of the layer "persistence"
"de.schauderhaft.*.(*).**") // for everything else use the fourth part of the package name as the name of the layer
) should be(violationFree) // check for violations (i.e. dependency circles)

The equivalent test code in Java and JUnit looks like this:

assertThat(
classpath() // analyze everything found in the current classpath
.including("de.schauderhaft.**") // only the classes that start with "de.schauderhaft."
.withSlicing("module", "de.schauderhaft.(*).**") // use the third part of the package name as the module name, and make sure the modules don't have cycles
.withSlicing("layer",
new NamedPattern("persistence","de.schauderhaft.legacy.db.**"), // consider everything in the package de.schauderhaft.legacy.db and subpackages as part of the layer "persistence"
"de.schauderhaft.*.(*).**") // for everything else use the fourth part of the package name as the name of the layer
),
is(violationFree())
);

You can also constrain the ways different slices depend on each other. For example

…
.withSlicing("module", "de.schauderhaft.(*).**").allow(oneOf("order", "reporting"), "customer", "core")
…

Means:

  • stuff in de.schauderhaft.order may depend onde.schauderhaft.customer and de.schauderhaft.core
  • the same is true for de.schauderhaft.reporting
  • de.schauderhaft.customer may depend onde.schauderhaft.core
  • all other dependencies between those packages are disallowed
  • packages from and to other packages are allowed

If you also want to allow dependencies between the order slice and the reporting slice replace oneOf with anyOf.

If you want to disallow dependencies from reporting or order tocore you can replace allow with allowDirect.

See the official documentation for more details, especially all theoptions the DSL offers, the imports needed and how to set up Degraph for testing.

I’m trying to get Degraph into maven central to make usage inside projects easier.
I also have some changes to the testing DSL on my to-do list. And finally I’m working on a HTML5 based front end. So stay tuned.

And as always: Feedback including feature requests and pull requestsis welcome.

Download “The DevOps Journey - From Waterfall to Continuous Delivery” to learn learn about the importance of integrating automated testing into the DevOps workflow, brought to you in partnership with Sauce Labs.

Topics:

Published at DZone with permission of Jens Schauder, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}