2015-11-10 2 views
1

Я ищу использовать платформу Slick 3 для приложения Scala для управления взаимодействием с базами данных. Я смог автоматически генерировать необходимые объекты таблицы с помощью Slick, но Мне также нужен интеграционный тест, который проверяет соответствие схем в базе данных схемам объектов. Это потому, что иногда таблицы меняются без предупреждения моей команды, поэтому мы предпочли бы уловить изменение в тесте интеграции вместо производственного приложения.Проверка схемы с помощью Slick 3

Один из способов сделать это - просто запустить запрос выбора для каждой отдельной таблицы в тестовом бегуне. Тем не менее, я чувствую, что должен быть более прямой путь. Кроме того, мне непонятно, как систематически выполнять все таблицы, определенные в файле, за исключением того, что вручную добавляет объект таблицы к некоторой последовательности, через которую проходит тестовый бегун. Я заметил, что есть поле схемы, но у него есть возможность генерировать операторы создания и удаления.

Любая помощь была бы принята с благодарностью. Спасибо!

EDIT:

Вот мое решение, но я надеялся на лучшее один:

class TablesIT extends FunSuite with BeforeAndAfter with ScalaFutures { 
    var db: Database = _ 
    before{ db = Database.forURL(/* personal details */)} 

    object ResultMap extends GetResult[Map[String,Any]] { //Object borrowed from http://stackoverflow.com/questions/20262036/slick-query-multiple-tables-databases-with-getting-column-names 
    def apply(pr: PositionedResult) = { 
     val rs = pr.rs // <- jdbc result set 
     val md = rs.getMetaData 
     val res = (1 to pr.numColumns).map{ i=> md.getColumnName(i) -> rs.getObject(i) }.toMap 
     pr.nextRow // <- use Slick's advance method to avoid endless loop 
     res 
    } 
    } 

    def testTableHasCols[A <: Table[_]](table: slick.lifted.TableQuery[A]): Unit = { 
    whenReady(db.run(table.take(1).result.headOption.asTry)) { case Success(t) => t match { 
     case Some(r) => logTrace(r.toString) 
     case None => logTrace("Empty table") 
    } 
    case Failure(ex) => fail("Query exception: " + ex.toString) 
    } 
    } 

    def plainSqlSelect[A](query: String)(implicit gr: GetResult[A]): Future[Seq[A]] = { 
    val stmt = sql"""#$query""".as[A] 
    db.run(stmt) 
    } 


    def compareNumOfCols[A <: Table[_]](table: slick.lifted.TableQuery[A]) = { 
    val tableName = table.baseTableRow.tableName 
    val selectStar = whenReady(db.run(sql"""select * from #$tableName limit 1""".as(ResultMap).headOption)) { 
     case Some(m) => m.size 
     case None => 0 
    } 
    val model = whenReady(db.run(sql"""#${table.take(1).result.statements.head}""".as(ResultMap).headOption)) { 
     case Some(m) => m.size 
     case None => 0 
    } 
    assert(selectStar === model, "The number of columns do not match") 
    } 

    test("Test table1") { 
    testTableHasCols(Table1) 
    compareNumOfCols(Table1) 
    } 

// And on for each table 
} 
+0

Вы нашли какую-либо другую идею? – daydreamer

+0

Да, на самом деле. Позвольте мне опубликовать его в качестве ответа. – user3846506

ответ

1

я в конечном итоге разработки лучшее решение, которое использует следующую идею. Это более или менее то же самое, и, к сожалению, мне все же приходится вручную создавать тест для каждой таблицы, но, по-моему, метод чище. Обратите внимание, однако, что это работает только для PostgreSQL из-за информационной схемы, но другие системы баз данных имеют другие методы.

class TablesIT extends FunSuite with BeforeAndAfter with ScalaFutures { 
    var db: Database = _ 
    before{ db = Database.forURL(/* personal details */)} 

    def testTableHasCols[A <: Table[_]](table: slick.lifted.TableQuery[A]): Unit = { 
    whenReady(db.run(table.take(1).result.headOption.asTry)) { case Success(t) => t match { 
     case Some(r) => logTrace(r.toString) 
     case None => logTrace("Empty table") 
    } 
    case Failure(ex) => fail("Query exception: " + ex.toString) 
    } 
    } 

    def compareNumOfCols[A <: Table[_]](table: slick.lifted.TableQuery[A]) = { 
    val tableName = table.baseTableRow.tableName 
    val selectStar = whenReady(db.run(sql"""select column_name from information_schema.columns where table_name='#$tableName'""".as[String])) { 
     case m: Seq[String] => m.size 
     case _ => 0 
    } 
    val model = table.baseTableRow.create_*.map(_.name).toSeq.size 

    assert(selectStar === model, "The number of columns do not match") 
    } 

    test("Test table1") { 
    testTableHasCols(Table1) 
    compareNumOfCols(Table1) 
    } 

// And on for each table 
} 
+0

Обратите внимание, что при проектировании это не гарантирует ** порядок ** столбцов в таблицах. – user3846506

Смежные вопросы