diff --git a/pom.xml b/pom.xml index d1cded3..20e8459 100644 --- a/pom.xml +++ b/pom.xml @@ -77,15 +77,32 @@ spring-test true + + org.mybatis + mybatis + 3.5.2 + + + org.junit.jupiter + junit-jupiter-api + 5.5.2 + + + org.junit.jupiter + junit-jupiter-engine + 5.5.2 + junit junit 4.12 + test - org.mybatis - mybatis - 3.5.2 + org.testcontainers + junit-jupiter + 1.12.2 + test org.testcontainers @@ -103,6 +120,11 @@ + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + org.apache.maven.plugins maven-compiler-plugin diff --git a/src/main/java/com/tyro/oss/dbevolution/LiquiBaseMigrationScriptTestBase.java b/src/main/java/com/tyro/oss/dbevolution/LiquiBaseMigrationScriptTestBase.java deleted file mode 100644 index 625fbce..0000000 --- a/src/main/java/com/tyro/oss/dbevolution/LiquiBaseMigrationScriptTestBase.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2019 Tyro Payments Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.tyro.oss.dbevolution; - -import com.tyro.oss.dbevolution.database.DatabaseHelper; -import liquibase.Liquibase; -import liquibase.database.jvm.JdbcConnection; -import liquibase.exception.LiquibaseException; -import liquibase.resource.ClassLoaderResourceAccessor; -import org.apache.commons.beanutils.BeanUtilsBean; -import org.apache.commons.beanutils.ConvertUtilsBean; -import org.apache.commons.beanutils.Converter; -import org.apache.ddlutils.model.Database; -import org.junit.BeforeClass; -import org.junit.Test; -import org.springframework.core.io.Resource; - -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; - -import static org.apache.ddlutils.PlatformFactory.createNewPlatformInstance; -import static org.junit.Assert.fail; - -public abstract class LiquiBaseMigrationScriptTestBase { - - public static DatabaseHelper databaseHelper; - public static Resource schemaSnapshot; - public static MigrationScriptsVerifier migrationScriptsVerifier; - - LiquiBaseMigrationTestDefinition definition; - - @BeforeClass - public static void runOnce() { - try { - databaseHelper.dropAndRecreateDatabaseFromSnapshot(schemaSnapshot); - } catch (Exception e) { - System.err.println("Failed to install starting schema: " + e); - e.printStackTrace(); - fail("Failed to install starting schema: " + e); - } - } - - @BeforeClass - public static void setUpConverterForBitColumns() { - ConvertUtilsBean convertUtils = BeanUtilsBean.getInstance().getConvertUtils(); - final Converter originalBooleanConverter = convertUtils.lookup(Boolean.class); - convertUtils.register((type, value) -> { - if (Boolean.class.equals(type)) { - if ("b'1'".equals(value)) { - return Boolean.TRUE; - } else if ("b'0'".equals(value)) { - return Boolean.FALSE; - } - } - return originalBooleanConverter.convert(type, value); - }, Boolean.class); - } - - @Test - public void testDefinitionMigration() throws SQLException, LiquibaseException { - try { - definition.assertPreMigrationSchema(getDatabase(), getConnection()); - if (definition.disableReferentialIntegrityForInsertingPreMigrationData()) { - setReferentialIntegrity(false); - } - try { - definition.insertPreMigrationData(getConnection()); - getConnection().commit(); - } finally { - setReferentialIntegrity(true); - } - definition.assertPreMigrationData(getConnection()); - executeScript(); - definition.assertPostMigrationSchema(getDatabase(), getConnection()); - definition.assertPostMigrationData(getConnection()); - getConnection().commit(); - } finally { - getConnection().close(); - } - } - - public void allScriptsShouldBeTestedAndHavePreconditionsAndAllTestedFilesIncluded() throws Exception { - migrationScriptsVerifier.allScriptsShouldBeTestedAndHavePreconditionsAndAllTestedFilesIncluded(); - } - - private void setReferentialIntegrity(boolean on) throws SQLException { - String statementString = "SET FOREIGN_KEY_CHECKS = " + (on ? "1" : "0"); - Statement statement = databaseHelper.getConnection().createStatement(); - statement.execute(statementString); - statement.close(); - } - - private Connection getConnection() throws SQLException { - return databaseHelper.getConnection(); - } - - private Database getDatabase() throws SQLException { - return createNewPlatformInstance(databaseHelper.getDataSource()).readModelFromDatabase( - getConnection(), - databaseHelper.getDatabaseDetails().getSchemaName(), - databaseHelper.getDatabaseDetails().getSchemaName(), - null, - null); - } - - private void executeScript() throws SQLException, LiquibaseException { - String migrationScript = definition.getMigrationScriptFilename(); - Liquibase migrator = new Liquibase(migrationScript, new ClassLoaderResourceAccessor(), new JdbcConnection(getConnection())); - migrator.update("production"); - } -} - diff --git a/src/main/java/com/tyro/oss/dbevolution/LiquiBaseMigrationScriptsTestRunner.java b/src/main/java/com/tyro/oss/dbevolution/LiquiBaseMigrationScriptsTestRunner.java deleted file mode 100644 index 0aa7d58..0000000 --- a/src/main/java/com/tyro/oss/dbevolution/LiquiBaseMigrationScriptsTestRunner.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2019 Tyro Payments Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.tyro.oss.dbevolution; - -import com.tyro.oss.dbevolution.database.DatabaseHelper; -import com.tyro.oss.dbevolution.database.DatabaseHelperFactory; -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.junit.runner.notification.RunNotifier; -import org.junit.runners.BlockJUnit4ClassRunner; -import org.junit.runners.model.FrameworkMethod; -import org.junit.runners.model.TestClass; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; - -import javax.sql.DataSource; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -public class LiquiBaseMigrationScriptsTestRunner extends BlockJUnit4ClassRunner { - - private final List children = new ArrayList<>(); - private final DatabaseHelper databaseHelper; - private final String migrationScriptFilename; - private final Resource schemaSnapshot; - private final MigrationScriptsVerifier migrationScriptsVerifier; - - public LiquiBaseMigrationScriptsTestRunner(Class clazz) throws Exception { - super(clazz); - - SchemaDetails schemaDetails = clazz.getAnnotation(SchemaDetails.class); - MigrationScript migrationScript = clazz.getAnnotation(MigrationScript.class); - - try { - this.schemaSnapshot = new ClassPathResource(schemaDetails.snapshotScript()); - this.migrationScriptFilename = migrationScript.filename(); - } catch (NullPointerException npe) { - throw new NullPointerException("Please specify a @SchemaDetails and @MigrationScript annotation in your test."); - } - - databaseHelper = DatabaseHelperFactory.newInstance(schemaDetails, schemaSnapshot); - - DataSource dataSource = databaseHelper.getDataSource(); - - try { - Method declaredMethod = clazz.getDeclaredMethod("getTestDefinitions"); - List testDefinitions = (List) declaredMethod.invoke(null, null); - - for (LiquiBaseMigrationTestDefinition testDefinition : testDefinitions) { - children.add(new LiquiBaseMigrationScriptTesterFrameworkMethod(testDefinition)); - } - - migrationScriptsVerifier = new MigrationScriptsVerifier(databaseHelper, dataSource.getConnection(), this.schemaSnapshot, migrationScriptFilename, testDefinitions); - - children.add(new FrameworkMethod(LiquiBaseMigrationScriptTestBase.class.getDeclaredMethod("allScriptsShouldBeTestedAndHavePreconditionsAndAllTestedFilesIncluded"))); - - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - @Override - protected org.junit.runners.model.Statement classBlock(RunNotifier notifier) { - setDatabaseMigrationFieldsOntoTest(); - return super.classBlock(notifier); - } - - private void setDatabaseMigrationFieldsOntoTest() { - TestClass testClass = getTestClass(); - Class testBaseClass = (Class) testClass.getJavaClass(); - - try { - Field databaseHelper = testBaseClass.getField("databaseHelper"); - databaseHelper.set(null, this.databaseHelper); - - Field schemaSnapshot = testBaseClass.getField("schemaSnapshot"); - schemaSnapshot.set(null, this.schemaSnapshot); - - Field migrationScriptsVerifier = testBaseClass.getField("migrationScriptsVerifier"); - migrationScriptsVerifier.set(null, this.migrationScriptsVerifier); - - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - @Override - public List getChildren() { - return children; - } - - private class LiquiBaseMigrationScriptTesterFrameworkMethod extends FrameworkMethod { - - private final LiquiBaseMigrationTestDefinition definition; - - public LiquiBaseMigrationScriptTesterFrameworkMethod(LiquiBaseMigrationTestDefinition definition) throws NoSuchMethodException { - super(LiquiBaseMigrationScriptTestBase.class.getDeclaredMethod("testDefinitionMigration")); - this.definition = definition; - } - - @Override - public Object invokeExplosively(Object target, Object... params) throws Throwable { - ((LiquiBaseMigrationScriptTestBase) target).definition = definition; - return super.invokeExplosively(target, params); - } - - @Override - public String getName() { - return definition.getMigrationName(); - } - - @Override - public boolean equals(Object other) { - return EqualsBuilder.reflectionEquals(this, other); - } - - @Override - public int hashCode() { - return HashCodeBuilder.reflectionHashCode(this); - } - } -} diff --git a/src/main/java/com/tyro/oss/dbevolution/LiquibaseMigrationScriptTestBase.java b/src/main/java/com/tyro/oss/dbevolution/LiquibaseMigrationScriptTestBase.java new file mode 100644 index 0000000..1fe210e --- /dev/null +++ b/src/main/java/com/tyro/oss/dbevolution/LiquibaseMigrationScriptTestBase.java @@ -0,0 +1,146 @@ +/* + * Copyright 2019 Tyro Payments Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.tyro.oss.dbevolution; + +import com.tyro.oss.dbevolution.database.DatabaseHelper; +import com.tyro.oss.dbevolution.database.DatabaseHelperFactory; +import liquibase.Liquibase; +import liquibase.database.jvm.JdbcConnection; +import liquibase.exception.LiquibaseException; +import liquibase.resource.ClassLoaderResourceAccessor; +import org.apache.commons.beanutils.BeanUtilsBean; +import org.apache.commons.beanutils.ConvertUtilsBean; +import org.apache.commons.beanutils.Converter; +import org.apache.ddlutils.model.Database; +import org.junit.jupiter.api.*; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Collection; +import java.util.stream.Stream; + +import static java.lang.String.format; +import static org.apache.ddlutils.PlatformFactory.createNewPlatformInstance; +import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.DynamicTest.dynamicTest; +import static org.junit.jupiter.api.MethodOrderer.OrderAnnotation; + +@TestMethodOrder(OrderAnnotation.class) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public abstract class LiquibaseMigrationScriptTestBase { + + protected String migrationScriptFilename; + protected Resource schemaSnapshot; + protected DatabaseHelper databaseHelper; + + @BeforeAll + protected void setUpConverterForBitColumns() { + ConvertUtilsBean convertUtils = BeanUtilsBean.getInstance().getConvertUtils(); + Converter originalBooleanConverter = convertUtils.lookup(Boolean.class); + convertUtils.register((type, value) -> { + if (Boolean.class.equals(type)) { + if ("b'1'".equals(value)) { + return Boolean.TRUE; + } else if ("b'0'".equals(value)) { + return Boolean.FALSE; + } + } + return originalBooleanConverter.convert(type, value); + }, Boolean.class); + } + + @BeforeAll + protected void setUpDatabase() { + SchemaDetails schemaDetails = this.getClass().getAnnotation(SchemaDetails.class); + MigrationScript migrationScript = this.getClass().getAnnotation(MigrationScript.class); + + try { + schemaSnapshot = new ClassPathResource(schemaDetails.snapshotScript()); + migrationScriptFilename = migrationScript.filename(); + } catch (NullPointerException e) { + throw new NullPointerException("Please specify a @SchemaDetails and @MigrationScript annotation in your test."); + } + + try { + databaseHelper = DatabaseHelperFactory.newInstance(schemaDetails, schemaSnapshot); + databaseHelper.dropAndRecreateDatabaseFromSnapshot(schemaSnapshot); + } catch (Exception e) { + fail("Failed to install starting schema", e); + } + } + + @TestFactory + @Order(1) + protected Stream liquibaseMigrations() { + return testDefinitions() + .stream() + .map(definition -> dynamicTest(definition.getMigrationName(), () -> testDefinitionMigration(definition))); + } + + @Test + @Order(2) + protected void allScriptsShouldBeTestedAndHavePreconditionsAndAllTestedFilesIncluded() throws Exception { + MigrationScriptsVerifier migrationScriptsVerifier = new MigrationScriptsVerifier(databaseHelper, databaseHelper.getDataSource().getConnection(), this.schemaSnapshot, migrationScriptFilename, testDefinitions()); + migrationScriptsVerifier.allScriptsShouldBeTestedAndHavePreconditionsAndAllTestedFilesIncluded(); + } + + protected abstract Collection testDefinitions(); + + private void testDefinitionMigration(LiquibaseMigrationTestDefinition definition) throws SQLException, LiquibaseException { + try (Connection connection = databaseHelper.getConnection()) { + definition.assertPreMigrationSchema(getDatabase(), connection); + if (definition.disableReferentialIntegrityForInsertingPreMigrationData()) { + setReferentialIntegrity(false); + } + try { + definition.insertPreMigrationData(connection); + connection.commit(); + } finally { + setReferentialIntegrity(true); + } + definition.assertPreMigrationData(connection); + executeScript(definition); + definition.assertPostMigrationSchema(getDatabase(), connection); + definition.assertPostMigrationData(connection); + connection.commit(); + } + } + + private void setReferentialIntegrity(boolean on) throws SQLException { + try (Statement statement = databaseHelper.getConnection().createStatement()) { + statement.execute(format("SET FOREIGN_KEY_CHECKS = %s", on ? "1" : "0")); + } + } + + private Database getDatabase() throws SQLException { + return createNewPlatformInstance(databaseHelper.getDataSource()) + .readModelFromDatabase( + databaseHelper.getConnection(), + databaseHelper.getDatabaseDetails().getSchemaName(), + databaseHelper.getDatabaseDetails().getSchemaName(), + null, + null); + } + + private void executeScript(LiquibaseMigrationTestDefinition definition) throws SQLException, LiquibaseException { + String migrationScript = definition.getMigrationScriptFilename(); + Liquibase migrator = new Liquibase(migrationScript, new ClassLoaderResourceAccessor(), new JdbcConnection(databaseHelper.getConnection())); + migrator.update("production"); + } +} diff --git a/src/main/java/com/tyro/oss/dbevolution/LiquiBaseMigrationTestDefinition.java b/src/main/java/com/tyro/oss/dbevolution/LiquibaseMigrationTestDefinition.java similarity index 94% rename from src/main/java/com/tyro/oss/dbevolution/LiquiBaseMigrationTestDefinition.java rename to src/main/java/com/tyro/oss/dbevolution/LiquibaseMigrationTestDefinition.java index c6b039b..f209a78 100644 --- a/src/main/java/com/tyro/oss/dbevolution/LiquiBaseMigrationTestDefinition.java +++ b/src/main/java/com/tyro/oss/dbevolution/LiquibaseMigrationTestDefinition.java @@ -25,25 +25,25 @@ import java.util.ArrayList; import java.util.List; -public abstract class LiquiBaseMigrationTestDefinition { +public abstract class LiquibaseMigrationTestDefinition { private final String migrationName; private final String migrationScriptLocation; private final boolean allowAnyPreconditionOnFailHandling; - public LiquiBaseMigrationTestDefinition() { + public LiquibaseMigrationTestDefinition() { this.allowAnyPreconditionOnFailHandling = false; this.migrationName = getClass().getSimpleName(); this.migrationScriptLocation = deriveMigrationScriptLocationFromTestPackage(); } - public LiquiBaseMigrationTestDefinition(boolean allowAnyPreconditionOnFailHandling) { + public LiquibaseMigrationTestDefinition(boolean allowAnyPreconditionOnFailHandling) { this.allowAnyPreconditionOnFailHandling = allowAnyPreconditionOnFailHandling; this.migrationName = getClass().getSimpleName(); this.migrationScriptLocation = deriveMigrationScriptLocationFromTestPackage(); } - public LiquiBaseMigrationTestDefinition(String migrationScriptLocation) { + public LiquibaseMigrationTestDefinition(String migrationScriptLocation) { this.allowAnyPreconditionOnFailHandling = false; this.migrationName = getClass().getSimpleName(); this.migrationScriptLocation = migrationScriptLocation; diff --git a/src/main/java/com/tyro/oss/dbevolution/MigrationScriptsVerifier.java b/src/main/java/com/tyro/oss/dbevolution/MigrationScriptsVerifier.java index 3c04823..5adabc4 100644 --- a/src/main/java/com/tyro/oss/dbevolution/MigrationScriptsVerifier.java +++ b/src/main/java/com/tyro/oss/dbevolution/MigrationScriptsVerifier.java @@ -29,14 +29,12 @@ import org.springframework.core.io.Resource; import java.sql.Connection; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; +import static java.lang.String.format; import static liquibase.precondition.core.PreconditionContainer.ErrorOption; import static liquibase.precondition.core.PreconditionContainer.FailOption; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; public class MigrationScriptsVerifier { @@ -44,12 +42,12 @@ public class MigrationScriptsVerifier { private final Connection connection; private final String migrationScriptsFilename; private final Resource schemaFile; + private final List changeSetFilesUnderTest; + private final Set changesetPreconditionExclusions; private List newChangeSetFilesCompleted; - private List changeSetFilesUnderTest; private DatabaseChangeLog changeLog; - private Set changesetPreconditionExclusions; - MigrationScriptsVerifier(DatabaseHelper databaseHelper, Connection connection, Resource schemaFile, String migrationScriptsFilename, List testDefinitions) { + MigrationScriptsVerifier(DatabaseHelper databaseHelper, Connection connection, Resource schemaFile, String migrationScriptsFilename, Collection testDefinitions) { this.databaseHelper = databaseHelper; this.connection = connection; this.schemaFile = schemaFile; @@ -57,7 +55,7 @@ public class MigrationScriptsVerifier { this.changesetPreconditionExclusions = new HashSet<>(); changeSetFilesUnderTest = new ArrayList<>(); - for (LiquiBaseMigrationTestDefinition testDefinition : testDefinitions) { + for (LiquibaseMigrationTestDefinition testDefinition : testDefinitions) { changeSetFilesUnderTest.add(testDefinition.getMigrationScriptFilename()); if (testDefinition.isAllowAnyPreconditionOnFailHandling()) { changesetPreconditionExclusions.add(testDefinition.getMigrationScriptFilename()); @@ -104,12 +102,15 @@ private void checkAllChangeLogsHaveAppropriatePreconditions() { PreconditionContainer preconditions = changeSet.getPreconditions(); - assertNotNull(changeSetName + " has no preconditions. Preconditions are required.", preconditions); + assertNotNull(preconditions, + format("%s has no preconditions. Preconditions are required.", changeSetName)); - assertEquals(changeSetName + " should HALT on error.", ErrorOption.HALT, preconditions.getOnError()); + assertEquals(ErrorOption.HALT, preconditions.getOnError(), + format("%s should HALT on error.", changeSetName)); if (!changesetPreconditionExclusions.contains(changeSetName)) { - assertEquals(changeSetName + " should HALT on fail.", FailOption.HALT, preconditions.getOnFail()); + assertEquals(FailOption.HALT, preconditions.getOnFail(), + format("%s should HALT on fail.", changeSetName)); } else { System.out.println("Skipping precondition check for " + changeSetName); } @@ -118,8 +119,8 @@ private void checkAllChangeLogsHaveAppropriatePreconditions() { private void checkAllChangeLogsNamedInTestsHaveBeenExecuted() { for (String changeSetInDatabaseMigrationScriptsFile : newChangeSetFilesCompleted) { - assertTrue("There is no test listed for the " + changeSetInDatabaseMigrationScriptsFile + " migration script.", - changeSetFilesUnderTest.contains(changeSetInDatabaseMigrationScriptsFile)); + assertTrue(changeSetFilesUnderTest.contains(changeSetInDatabaseMigrationScriptsFile), + "There is no test listed for the " + changeSetInDatabaseMigrationScriptsFile + " migration script."); } } @@ -127,11 +128,11 @@ private void checkAllChangeLogsNamedInScriptListFileHaveBeenTested() { for (String changeSetUnderTest : changeSetFilesUnderTest) { boolean isExtraReleaseScript = changeSetUnderTest.startsWith("extra-release"); if (!isExtraReleaseScript) { - assertTrue("The " + changeSetUnderTest + " migration script does not appear in " + migrationScriptsFilename + " or was already run before the current snapshot.", - newChangeSetFilesCompleted.contains(changeSetUnderTest)); + assertTrue(newChangeSetFilesCompleted.contains(changeSetUnderTest), + format("The %s migration script does not appear in %s or was already run before the current snapshot.", changeSetUnderTest, migrationScriptsFilename)); } else { - assertFalse("The " + changeSetUnderTest + " migration script SHOULD NOT appear in " + migrationScriptsFilename + " because it is an extra-release script and should not be run automatically.", - newChangeSetFilesCompleted.contains(changeSetUnderTest)); + assertFalse(newChangeSetFilesCompleted.contains(changeSetUnderTest), + format("The %s migration script SHOULD NOT appear in %s because it is an extra-release script and should not be run automatically.", changeSetUnderTest, migrationScriptsFilename)); } } } diff --git a/src/main/java/com/tyro/oss/dbevolution/assertions/ColumnAssert.java b/src/main/java/com/tyro/oss/dbevolution/assertions/ColumnAssert.java index f4028f9..392d63d 100644 --- a/src/main/java/com/tyro/oss/dbevolution/assertions/ColumnAssert.java +++ b/src/main/java/com/tyro/oss/dbevolution/assertions/ColumnAssert.java @@ -31,11 +31,11 @@ import java.util.Map; import static com.tyro.oss.dbevolution.assertions.ColumnAssert.StandardStringColumnAssertions.DEFAULT_VARCHAR_MAX_LENGTH; -import static com.tyro.oss.dbevolution.assertions.SchemaAssert.*; import static java.lang.String.format; import static java.util.Arrays.asList; import static java.util.Arrays.stream; import static java.util.stream.Collectors.toList; +import static org.junit.jupiter.api.Assertions.*; public class ColumnAssert { @@ -56,19 +56,21 @@ public ColumnAssert(Database schema, TableAssert tableAssert, String columnName) private static void assertColumnSize(Database database, String tableName, String columnName, int columnSize) { Table table = database.findTable(tableName); - assertEquals("Size of " + tableName + "." + columnName, columnSize, table.findColumn(columnName).getSizeAsInt()); + assertEquals(columnSize, table.findColumn(columnName).getSizeAsInt(), + format("Size of %s.%s", tableName, columnName)); } private static void assertColumnMinimalSize(Database database, String tableName, String columnName, int columnSize) { Table table = database.findTable(tableName); int actualColumnSize = table.findColumn(columnName).getSizeAsInt(); - String message = format("Size of %s.%s should be at least %d, but was %s.", tableName, columnName, columnSize, actualColumnSize); - assertTrue(message, actualColumnSize >= columnSize); + assertTrue(actualColumnSize >= columnSize, + format("Size of %s.%s should be at least %d, but was %s.", tableName, columnName, columnSize, actualColumnSize)); } private static void assertColumnScale(Database database, String tableName, String columnName, int columnScale) { Table table = database.findTable(tableName); - assertEquals("Scale of " + tableName + "." + columnName, columnScale, table.findColumn(columnName).getScale()); + assertEquals(columnScale, table.findColumn(columnName).getScale(), + format("Scale of %s.%s", tableName, columnName)); } private static void assertColumnIsTypeAndSize(Database database, String tableName, String columnName, int type, int columnSize) { @@ -78,13 +80,16 @@ private static void assertColumnIsTypeAndSize(Database database, String tableNam private static void assertColumnIsType(Database database, String tableName, String columnName, int sqlType) { Column column = database.findTable(tableName).findColumn(columnName); - assertNotNull("Column '" + columnName + "' does not exist.", column); - assertEquals("Type of " + tableName + "." + columnName, sqlTypeToString(sqlType), sqlTypeToString(column.getTypeCode())); + assertNotNull(column, + format("Column '%s' does not exist.", columnName)); + assertEquals(sqlTypeToString(sqlType), sqlTypeToString(column.getTypeCode()), + format("Type of %s.%s", tableName, columnName)); } private static void assertColumnIsType(Database database, String tableName, String columnName, int... sqlTypes) { Column column = database.findTable(tableName).findColumn(columnName); - assertNotNull("Column '" + columnName + "' does not exist.", column); + assertNotNull(column, + format("Column '%s' does not exist.", columnName)); String actualType = sqlTypeToString(column.getTypeCode()); @@ -92,8 +97,8 @@ private static void assertColumnIsType(Database database, String tableName, Stri .mapToObj(ColumnAssert::sqlTypeToString) .collect(toList()); - String message = format("Type of %s.%s should be one of %s, but was %s.", tableName, columnName, expectedTypes, actualType); - assertTrue(message, expectedTypes.contains(actualType)); + assertTrue(expectedTypes.contains(actualType), + format("Type of %s.%s should be one of %s, but was %s.", tableName, columnName, expectedTypes, actualType)); } private static String sqlTypeToString(int sqlType) { @@ -128,13 +133,15 @@ private static void assertColumnIsZoneIdType(Database database, String tableName private static void assertColumnIsNullable(Database database, String tableName, String columnName) { Table table = database.findTable(tableName); - assertFalse(tableName + "." + columnName + " should be nullable", table.findColumn(columnName).isRequired()); + assertFalse(table.findColumn(columnName).isRequired(), + format("%s.%s should be nullable", tableName, columnName)); } private static void assertColumnIsNotNullable(Database database, String tableName, String columnName) { Table table = database.findTable(tableName); Column column = table.findColumn(columnName); - assertTrue(tableName + "." + columnName + " should be NOT NULL", column.isRequired()); + assertTrue(column.isRequired(), + format("%s.%s should be NOT NULL", tableName, columnName)); } private static void assertColumnHasDefaultValue(Database database, String tableName, String columnName, Object defaultValue) { @@ -191,12 +198,14 @@ public ColumnAssert isPresent() { private void assertColumnInTable(Database database, String tableName, String columnName) { Table table = database.findTable(tableName); - assertNotNull("Column '" + columnName + "' not present in '" + database.getName() + "." + tableName + "'", table.findColumn(columnName)); + assertNotNull(table.findColumn(columnName), + format("Column '%s' not present in '%s.%s'", columnName, database.getName(), tableName)); } private void assertColumnNotInTable(Database database, String tableName, String columnName) { Table table = database.findTable(tableName); - assertNull("Column " + tableName + "." + columnName + " should not exist", table.findColumn(columnName)); + assertNull(table.findColumn(columnName), + format("Column %s.%s should not exist", tableName, columnName)); } public ColumnAssert supportsType(Class hibernateFieldType) { @@ -303,25 +312,31 @@ public ColumnAssert isPrimaryKey() { for (int i = 0; i < table1.getColumns().length; i++) { String columnName = table1.getColumns()[i].getName(); if (asList(primaryKeyColumnNames).contains(columnName)) { - assertTrue(columnName + " should be a primary key member", table1.findColumn(columnName).isPrimaryKey()); + assertTrue(table1.findColumn(columnName).isPrimaryKey(), + format("%s should be a primary key member", columnName)); numberPrimaryKeys++; } } - assertEquals("Number of columns in " + table.getName() + "primary key", primaryKeyColumnNames.length, numberPrimaryKeys); + assertEquals(primaryKeyColumnNames.length, numberPrimaryKeys, + format("Number of columns in %sprimary key", table.getName())); return this; } public ColumnAssert isAutoIncrementing() { Column column = schema.findTable(table.getName()).findColumn(name); - assertNotNull("Column '" + name + "' does not exist.", column); - assertTrue(table.getName() + "." + name + " should be auto-increment", column.isAutoIncrement()); + assertNotNull(column, + format("Column '%s' does not exist.", name)); + assertTrue(column.isAutoIncrement(), + format("%s.%s should be auto-increment", table.getName(), name)); return this; } public ColumnAssert isNotAutoIncrementing() { Column column = schema.findTable(table.getName()).findColumn(name); - assertNotNull("Column '" + name + "' does not exist.", column); - assertFalse(table.getName() + "." + name + " should not be auto-increment", column.isAutoIncrement()); + assertNotNull(column, + format("Column '%s' does not exist.", name)); + assertFalse(column.isAutoIncrement(), + format("%s.%s should not be auto-increment", table.getName(), name)); return this; } @@ -334,7 +349,8 @@ String getName() { } public ForeignKeyAssert hasForeignKeyTo(String targetTable, String targetColumn) { - assertNotEquals(format("use hasForeignKeyTo(String targetTable) when the target column is \"%s\"", ID_COLUMN_NAME), ID_COLUMN_NAME, targetColumn); + assertNotEquals(ID_COLUMN_NAME, targetColumn, + format("use hasForeignKeyTo(String targetTable) when the target column is \"%s\"", ID_COLUMN_NAME)); return new ForeignKeyAssert(schema, this, targetTable, targetColumn).isPresent(); } @@ -343,7 +359,8 @@ public ColumnAssert doesNotHaveForeignKeyTo(String targetTable) { } public ColumnAssert doesNotHaveForeignKeyTo(String targetTable, String targetColumn) { - assertNotEquals(format("use doesNotHaveForeignKeyTo(String targetTable) when the target column is \"%s\"", ID_COLUMN_NAME), ID_COLUMN_NAME, targetColumn); + assertNotEquals(ID_COLUMN_NAME, targetColumn, + format("use doesNotHaveForeignKeyTo(String targetTable) when the target column is \"%s\"", ID_COLUMN_NAME)); return new ForeignKeyAssert(schema, this, targetTable, targetColumn).isNotPresent().andColumn(); } diff --git a/src/main/java/com/tyro/oss/dbevolution/assertions/DataAssert.java b/src/main/java/com/tyro/oss/dbevolution/assertions/DataAssert.java index 335280e..727515c 100644 --- a/src/main/java/com/tyro/oss/dbevolution/assertions/DataAssert.java +++ b/src/main/java/com/tyro/oss/dbevolution/assertions/DataAssert.java @@ -31,7 +31,7 @@ import static java.lang.String.format; import static org.apache.commons.lang3.StringUtils.join; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; public class DataAssert { @@ -47,7 +47,7 @@ public DataAssert isEmpty() throws SQLException { PreparedStatement statement = connection.prepareStatement("select count(*) from " + tableName); ResultSet result = statement.executeQuery(); result.next(); - assertEquals("Number of rows in " + tableName, 0, result.getInt(1)); + assertEquals(0, result.getInt(1), format("Number of rows in %s", tableName)); return this; } @@ -90,7 +90,7 @@ public DataAssert hasRowCount(int expectedRowCount) throws SQLException { ResultSet rs = ps.executeQuery(); assertTrue(rs.next()); long actualRowCount = rs.getLong(1); - assertEquals("# of rows in " + tableName, expectedRowCount, actualRowCount); + assertEquals(expectedRowCount, actualRowCount, format("# of rows in %s", tableName)); assertFalse(rs.next()); } @@ -101,7 +101,7 @@ public DataAssert hasRowsMatching(String tableA, String tableB, List col List rowsForTableA = getRowsForTable(tableA, columnNames, connection); List rowsForTableB = getRowsForTable(tableB, columnNames, connection); - assertEquals(format("%s does not have the same number of rows as %s", tableA, tableB), rowsForTableA.size(), rowsForTableB.size()); + assertEquals(rowsForTableA.size(), rowsForTableB.size(), format("%s does not have the same number of rows as %s", tableA, tableB)); assertEquals(rowsForTableA, rowsForTableB); return this; @@ -116,7 +116,8 @@ public DataAssert hasColumnsMatching(String[] columnA, String[] columnB) throws assertTrue(rs.next()); do { for (int i = 1; i < columnA.length + 1; i++) { - assertTrue("column " + columnA[i - 1] + " didn't match " + columnB[i - 1], rs.getBoolean(i)); + assertTrue(rs.getBoolean(i), + format("column %s didn't match %s", columnA[i - 1], columnB[i - 1])); } } while (rs.next()); diff --git a/src/main/java/com/tyro/oss/dbevolution/assertions/ForeignKeyAssert.java b/src/main/java/com/tyro/oss/dbevolution/assertions/ForeignKeyAssert.java index 8d054a7..f37ffa1 100644 --- a/src/main/java/com/tyro/oss/dbevolution/assertions/ForeignKeyAssert.java +++ b/src/main/java/com/tyro/oss/dbevolution/assertions/ForeignKeyAssert.java @@ -18,7 +18,8 @@ import org.apache.ddlutils.model.Database; import org.apache.ddlutils.model.ForeignKey; -import static org.junit.Assert.*; +import static java.lang.String.format; +import static org.junit.jupiter.api.Assertions.*; public class ForeignKeyAssert { @@ -51,18 +52,21 @@ private ForeignKey getForeignKey(ColumnAssert sourceColumn, String targetTable, } public ForeignKeyAssert isPresent() { - assertNotNull("Foreign Key not found for " + keyAsString, foreignKey); + assertNotNull(foreignKey, + format("Foreign Key not found for %s", keyAsString)); return this; } public ForeignKeyAssert isNotPresent() { - assertNull("Foreign Key exists for " + keyAsString, foreignKey); + assertNull(foreignKey, + format("Foreign Key exists for %s", keyAsString)); return this; } public ForeignKeyAssert withName(String expectedKeyName) { isPresent(); - assertEquals("Name of Foreign Key " + keyAsString, expectedKeyName, foreignKey.getName()); + assertEquals(expectedKeyName, foreignKey.getName(), + format("Name of Foreign Key %s", keyAsString)); return this; } diff --git a/src/main/java/com/tyro/oss/dbevolution/assertions/PrivilegeAssert.java b/src/main/java/com/tyro/oss/dbevolution/assertions/PrivilegeAssert.java index 6ef1444..9061fad 100644 --- a/src/main/java/com/tyro/oss/dbevolution/assertions/PrivilegeAssert.java +++ b/src/main/java/com/tyro/oss/dbevolution/assertions/PrivilegeAssert.java @@ -23,8 +23,8 @@ import static java.lang.String.format; import static java.util.stream.Collectors.toList; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; public class PrivilegeAssert { @@ -48,14 +48,16 @@ public PrivilegeAssert hasPrivilege(String schemaName, String tableName, EnumSet .map(Enum::name) .collect(toList()); - assertTrue(format("These privileges: %s should be granted to user: %s for table: %s.", missingPrivileges, username, tableName), missingPrivileges.isEmpty()); + assertTrue(missingPrivileges.isEmpty(), + format("These privileges: %s should be granted to user: %s for table: %s.", missingPrivileges, username, tableName)); List unexpectedPrivileges = tablePrivileges.stream() .filter(tablePrivilege -> !expectedPrivileges.contains(tablePrivilege)) .map(Enum::name) .collect(toList()); - assertTrue(format("These privileges: %s should not be granted to user: %s for table: %s.", unexpectedPrivileges, username, tableName), unexpectedPrivileges.isEmpty()); + assertTrue(unexpectedPrivileges.isEmpty(), + format("These privileges: %s should not be granted to user: %s for table: %s.", unexpectedPrivileges, username, tableName)); return this; } diff --git a/src/main/java/com/tyro/oss/dbevolution/assertions/SchemaAssert.java b/src/main/java/com/tyro/oss/dbevolution/assertions/SchemaAssert.java index c3bc1ab..89850ba 100644 --- a/src/main/java/com/tyro/oss/dbevolution/assertions/SchemaAssert.java +++ b/src/main/java/com/tyro/oss/dbevolution/assertions/SchemaAssert.java @@ -16,13 +16,12 @@ package com.tyro.oss.dbevolution.assertions; import org.apache.ddlutils.model.Database; -import org.junit.Assert; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.SQLException; -public class SchemaAssert extends Assert { +public class SchemaAssert { private final Database schema; private final DatabaseMetaData databaseMetadata; diff --git a/src/main/java/com/tyro/oss/dbevolution/assertions/TableAssert.java b/src/main/java/com/tyro/oss/dbevolution/assertions/TableAssert.java index 6731a4b..859d037 100644 --- a/src/main/java/com/tyro/oss/dbevolution/assertions/TableAssert.java +++ b/src/main/java/com/tyro/oss/dbevolution/assertions/TableAssert.java @@ -22,10 +22,11 @@ import java.util.Set; import static java.lang.String.format; +import static java.lang.String.join; import static java.util.Arrays.asList; import static java.util.Arrays.stream; import static java.util.stream.Collectors.toList; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; public class TableAssert { @@ -49,11 +50,13 @@ public TableAssert isNotPresent() { } private void assertTablePresent(Database database, String tableName) { - assertNotNull("Table '" + database.getName() + "." + tableName + "' not present", database.findTable(tableName)); + assertNotNull(database.findTable(tableName), + format("Table '%s.%s' not present", database.getName(), tableName)); } private void assertTableNotPresent(Database database, String tableName) { - assertNull("Table " + tableName + " should not exist", database.findTable(tableName)); + assertNull(database.findTable(tableName), + format("Table %s should not exist", tableName)); } public ColumnAssert hasColumn(String columnName) { @@ -86,7 +89,7 @@ public TableAssert hasUniqueIndexOn(String... columnNames) { } public TableAssert hasNoIndexes() { - assertEquals("Index count", 0, schema.findTable(name).getIndexCount()); + assertEquals(0, schema.findTable(name).getIndexCount(), "Index count"); return this; } @@ -102,9 +105,11 @@ private TableAssert testForIndexOnColumns(boolean wantToFindIndex, String... col Index matchingIndex = indexOnColumns(columnNames); if (wantToFindIndex) { - assertNotNull("No matching index found on column/s (" + String.join(",", columnNames) + ")", matchingIndex); + assertNotNull(matchingIndex, + format("No matching index found on column/s (%s)", join(",", columnNames))); } else { - assertNull("Matching index found on column " + String.join(",", columnNames), matchingIndex); + assertNull(matchingIndex, + format("Matching index found on column %s", join(",", columnNames))); } return this; } @@ -113,14 +118,18 @@ private TableAssert testForIndexOnColumns(boolean wantToFindIndex, boolean isUni Index matchingIndex = indexOnColumns(columnNames); if (wantToFindIndex) { - assertNotNull("No matching index found on column " + String.join(",", columnNames), matchingIndex); + assertNotNull(matchingIndex, + format("No matching index found on column %s", join(",", columnNames))); if (isUniqueIndex) { - assertTrue("Matching index found but not unique", matchingIndex.isUnique()); + assertTrue(matchingIndex.isUnique(), + "Matching index found but not unique"); } else { - assertFalse("Matching index found but it's specified as 'unique'", matchingIndex.isUnique()); + assertFalse(matchingIndex.isUnique(), + "Matching index found but it's specified as 'unique'"); } } else { - assertNull("Matching index found on column " + String.join(",", columnNames), matchingIndex); + assertNull(matchingIndex, + format("Matching index found on column %s", join(",", columnNames))); } return this; } @@ -147,9 +156,9 @@ private TableAssert testForIndexByName(boolean wantToFindIndex, String indexName .orElse(null); if (wantToFindIndex) { - assertNotNull("Matching index found", matchingIndex); + assertNotNull(matchingIndex, "Matching index not found"); } else { - assertNull("Matching index found", matchingIndex); + assertNull(matchingIndex, "Matching index found"); } return this; } @@ -179,7 +188,9 @@ public TableAssert hasForeignKeyOn(final String foreignTableName, final String l } } } - assertTrue(format("Foreign Key from column %s to table %s column %s does not exit", localTableColumn, foreignTableName, foreignTableColumn), matchFound); + + assertTrue(matchFound, + format("Foreign Key from column %s to table %s column %s does not exit", localTableColumn, foreignTableName, foreignTableColumn)); return this; } diff --git a/src/main/java/com/tyro/oss/dbevolution/assertions/ViewAssert.java b/src/main/java/com/tyro/oss/dbevolution/assertions/ViewAssert.java index 30abe11..564175d 100644 --- a/src/main/java/com/tyro/oss/dbevolution/assertions/ViewAssert.java +++ b/src/main/java/com/tyro/oss/dbevolution/assertions/ViewAssert.java @@ -23,8 +23,9 @@ import java.util.HashMap; import java.util.Map; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import static java.lang.String.format; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; public class ViewAssert { @@ -52,12 +53,14 @@ public ViewAssert(DatabaseMetaData databaseMetadata, Database schema, String vie } public ViewAssert isPresent() { - assertNotNull("View " + viewName + " does not exist.", columns); + assertNotNull(columns, + format("View %s does not exist.", viewName)); return this; } public void isNotPresent() { - assertNull("View " + viewName + " should not exist.", columns); + assertNull(columns, + format("View %s should not exist.", viewName)); } public ViewColumnAssert hasColumn(String columnName) { @@ -95,12 +98,14 @@ public ViewColumnAssert(String columnName, Column columns) { } public ViewColumnAssert isPresent() { - assertNotNull("Column " + columnName + " does not exist.", columns); + assertNotNull(columns, + format("Column %s does not exist.", columnName)); return this; } public void isNotPresent() { - assertNull("Column " + columnName + " should not exist.", columns); + assertNull(columns, + format("Column %s should not exist.", columnName)); } public ViewColumnAssert hasColumn(String columnName) { diff --git a/src/test/java/com/tyro/oss/dbevolution/CreateExampleTable.java b/src/test/java/com/tyro/oss/dbevolution/CreateExampleTable.java index aaf499b..d0833d3 100644 --- a/src/test/java/com/tyro/oss/dbevolution/CreateExampleTable.java +++ b/src/test/java/com/tyro/oss/dbevolution/CreateExampleTable.java @@ -22,7 +22,7 @@ import static com.tyro.oss.dbevolution.assertions.Assertions.assertThatSchema; -public class CreateExampleTable extends LiquiBaseMigrationTestDefinition { +public class CreateExampleTable extends LiquibaseMigrationTestDefinition { @Override protected void assertPreMigrationSchema(Database schema, Connection connection) { diff --git a/src/test/java/com/tyro/oss/dbevolution/LiquibaseScriptsTest.java b/src/test/java/com/tyro/oss/dbevolution/LiquibaseScriptsTest.java index 807ec92..a3c6810 100644 --- a/src/test/java/com/tyro/oss/dbevolution/LiquibaseScriptsTest.java +++ b/src/test/java/com/tyro/oss/dbevolution/LiquibaseScriptsTest.java @@ -15,27 +15,28 @@ */ package com.tyro.oss.dbevolution; -import org.junit.ClassRule; -import org.junit.runner.RunWith; import org.testcontainers.containers.MySQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; import java.util.List; import static java.util.Arrays.asList; -@RunWith(LiquiBaseMigrationScriptsTestRunner.class) +@Testcontainers @SchemaDetails( migrationUser = "test", migrationPassword = "test", url = "jdbc:tc:mysql://localhost/test?serverTimezone=UTC", snapshotScript = "schema.sql") @MigrationScript(filename = "migration-scripts.xml") -public class LiquibaseScriptsTest extends LiquiBaseMigrationScriptTestBase { +public class LiquibaseScriptsTest extends LiquibaseMigrationScriptTestBase { - @ClassRule - public static MySQLContainer mysql = new MySQLContainer(); + @Container + private final MySQLContainer mysql = new MySQLContainer(); - public static List getTestDefinitions() { + @Override + protected List testDefinitions() { return asList(new CreateExampleTable()); } }