Skip to content

Start with tests!

Joseph Hoare edited this page Mar 17, 2021 · 3 revisions

Tests are always important, but especially so when we're writing code intended to make changes in bulk. With great power comes great responsibility! For this reason, Astra provides a testing framework for its operations.

To use the testing framework, add astra-testing as a test scoped maven dependency:

    <dependency>
      <groupId>org.alfasoftware</groupId>
      <artifactId>astra-testing</artifactId>
      <version>${astra.version}</version>
      <scope>test</scope>
    </dependency>

The first thing to do is to figure out what you want to change, and how you want to change it. The best way to express that is to write out some before and after examples, as actual Java files. For example, if we want to refactor all uses of type A to type B, we might write this as an example of how a java file might look before our refactor:

import org.alfasoftware.astra.exampleTypes.A;
 
public class TypeReferenceExample {
  A field = A.staticMethod();
}

We name this TypeReferenceExample.java. Then, we move on to how we want it to look after we refactor it. We write the following class:

import org.alfasoftware.astra.exampleTypes.B;
 
public class TypeReferenceExampleAfter {
  B field = B.staticMethod();
}

We put this file in the same package as our previous example, and give it the same name, but suffixed with "After", so it becomes TypeReferenceExampleAfter.java.

Great! Now we effectively know what the input and the output of our refactor should look like.

We can use these actual Java files in a unit test. To do that, we write a new test class, which extends AbstractRefactorTest. We can then write a unit test which uses assertRefactor, a utility which takes the example .java file we wrote before, applies a given set of ASTOperations to it, and verifies that the output matches the After file:

public class TestTypeReferenceRefactor extends AbstractRefactorTest {

  @Test
  public void testChangeTypes() {
    assertRefactor(TypeReferenceExample.class,
        new HashSet<>(Arrays.asList(
          TypeReferenceRefactor.builder()
            .fromType(A.class.getName())
            .toType(B.class.getName())
            .build())));
  }
}

For details on how to write the refactor itself, please see Type reference refactor.