Skip to content

Tutorial 6. Structural Validation

Osman Shoukry edited this page Dec 16, 2015 · 6 revisions

What is it?

When talking about POJO validation we are always talking about getters/setters ...etc. Structural validation is different.

Structural validation is when you are trying to validate structurally your code base. Structural validation helps you answer questions like:

  1. Why does my IDE display different test counts than my command line or build servers?
  • Are my tests in the right location - i.e. do I have tests in production code?
  • ...etc.

TestClassMustBeProperlyNamedRule

A new class was introduced to help with structural validation called TestClassMustBeProperlyNamedRule.

It is designed to ensure that your tests are named properly so they will be run in the build server as well as they do in you IDE.

Examples

1. Ensuring all tests are named *Test.java | Test*.java | *TestCase.java

This is the default behavior in [maven-surefire-plugin] (https://maven.apache.org/surefire/maven-surefire-plugin/examples/inclusion-exclusion.html) and others
public class StructuralTest {
  // The package to be tested
  // Typically your top level package, you want to run this against everything
  private String topLevelPackageName = "com.mycompany";
  private PojoValidator pojoValidator;

  @Before
  public void setup() {
    pojoValidator = new PojoValidator();
    pojoValidator.addRule(new TestClassMustBeProperlyNamedRule());
  }

  @Test
  public void allTestsMustBeProperlyNamed() {
    List<PojoClass> pojoClasses = 
            PojoClassFactory.getPojoClassesRecursively(topLevelPackageName, null);
    for (PojoClass pojoClass : pojoClasses) {
      pojoValidator.runValidation(pojoClass);
    }
  }
}

2. For Integration tests are you'll want IT*.java *IT.java *ITCase.java

public class StructuralTest {
  // The package where you have your Integration Tests.
  private String topLevelPackageName = "com.mycompany.integrationtests";

  private PojoValidator pojoValidator;

  @Before
  public void setup() {
    // Create the required Prefixes
    List<String> prefixTokens = new ArrayList<String>();
    prefixTokens.add("IT");

    // Create the required Suffixes
    List<String> suffixTokens = new ArrayList<String>();
    suffixTokens.add("IT");
    suffixTokens.add("ITCase");    

    Rule testClassMustBeProperlyNamedRule =
            TestClassMustBeProperlyNamedRule(prefixTokens, suffixTokens);

    pojoValidator = new PojoValidator();
    pojoValidator.addRule(testClassMustBeProperlyNamedRule);
  }

  @Test
  public void allTestsMustBeProperlyNamed() {
    List<PojoClass> pojoClasses = 
            PojoClassFactory.getPojoClassesRecursively(topLevelPackageName, null);
    for (PojoClass pojoClass : pojoClasses) {
      pojoValidator.runValidation(pojoClass);
    }
  }
}

Is this really needed?

Go to your build server and look at the number of tests you have running on the build server look for a line like this:

Results :
Tests run: 756, Failures: 0, Errors: 0, Skipped: 0

Now run the build on your own IDE, what does it say? 756? if so you're good, if it says more, then you are suffering from unreliable Tests, ones that only run in your IDE but not on the build server.

For large projects, I have seen engineers falling behind and not run every test on their machine because the tests take too long, or require special setup that isn't readily accessible on their laptops leading to bugs making it all the way to production despite tests that were coded catch them!!