From 30fd83a6f205c6b91186e014c6ed893fb9a26795 Mon Sep 17 00:00:00 2001 From: Gregg Hernandez Date: Mon, 22 Jun 2015 17:07:12 -0600 Subject: [PATCH] move bootstrapping of it:test into code so SBT can manage it all. --- it-test.sh | 2 - project/ClientBuild.scala | 5 - .../lucidchart/open/relate/RelateITSpec.scala | 215 ++++++++++++++---- .../lucidchart/open/relate/row_insertion.sql | 52 ----- .../com/lucidchart/open/relate/setup.sql | 48 ---- 5 files changed, 168 insertions(+), 154 deletions(-) delete mode 100755 it-test.sh delete mode 100644 src/it/scala/com/lucidchart/open/relate/row_insertion.sql delete mode 100644 src/it/scala/com/lucidchart/open/relate/setup.sql diff --git a/it-test.sh b/it-test.sh deleted file mode 100755 index eefe8df..0000000 --- a/it-test.sh +++ /dev/null @@ -1,2 +0,0 @@ -mysql < src/it/scala/com/lucidchart/open/relate/row_insertion.sql; -sbt it:test; diff --git a/project/ClientBuild.scala b/project/ClientBuild.scala index 400dbdf..f572e3f 100644 --- a/project/ClientBuild.scala +++ b/project/ClientBuild.scala @@ -7,9 +7,4 @@ object ClientBuild extends Build { Project("root", file(".")) .configs(IntegrationTest) .settings(Defaults.itSettings: _*) - .settings( - testOptions in IntegrationTest += Tests.Setup( () => { - println("Make sure you're running these tests from this script: it-test.sh") - }) - ) } diff --git a/src/it/scala/com/lucidchart/open/relate/RelateITSpec.scala b/src/it/scala/com/lucidchart/open/relate/RelateITSpec.scala index bafc912..ea2a5e7 100644 --- a/src/it/scala/com/lucidchart/open/relate/RelateITSpec.scala +++ b/src/it/scala/com/lucidchart/open/relate/RelateITSpec.scala @@ -1,26 +1,147 @@ package com.lucidchart.open.relate +import com.lucidchart.open.relate.interp._ import com.lucidchart.open.relate.Query._ import java.sql.{DriverManager, Connection, SQLException} import org.specs2.mutable._ +import org.specs2.specification.Fragments +import org.specs2.specification.Step -class RelateITSpec extends Specification { - +trait Db { val url = "jdbc:mysql://localhost/" val dbName = "relate_it_tests" val driver = "com.mysql.jdbc.Driver" val user = "dev" val pass = "dev" + Class.forName(driver) - implicit val connection = try { - DriverManager.getConnection(url + dbName, user, pass) + + def withConnection[A](f: Connection => A): A = { + val connection = DriverManager.getConnection(url + dbName, user, pass) + f(connection) } - val streamConnection = try { - DriverManager.getConnection(url + dbName, user, pass) + + def createDb(): Unit = { + val noDbConn = DriverManager.getConnection(url, user, pass) + + sql"DROP DATABASE IF EXISTS relate_it_tests".execute()(noDbConn) + sql"CREATE DATABASE relate_it_tests".execute()(noDbConn) + + withConnection { implicit connection => + sql""" + CREATE TABLE pokedex ( + id BIGINT NOT NULL AUTO_INCREMENT, + name VARCHAR(50) NOT NULL, + description VARCHAR(200) NOT NULL, + PRIMARY KEY (id), + KEY name_key (name) + ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci + """.execute() + + sql""" + CREATE TABLE pokemon ( + id BIGINT NOT NULL AUTO_INCREMENT, + pokedex_id BIGINT NOT NULL, + level INT NOT NULL, + trainer_id BIGINT, + PRIMARY KEY(id), + KEY trainer_key (trainer_id) + ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci + """.execute() + + sql""" + CREATE TABLE professor_oaks_pokemon ( + id BIGINT NOT NULL AUTO_INCREMENT, + name VARCHAR(50) NOT NULL, + trainer_id BIGINT, + PRIMARY KEY(id), + KEY trainer_key (trainer_id) + ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci + """.execute() + + sql""" + CREATE TABLE undefeated_trainers ( + id BIGINT NOT NULL AUTO_INCREMENT, + name VARCHAR(50) NOT NULL, + PRIMARY KEY(id) + ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci + """.execute() + + sql""" + CREATE TABLE pagination ( + id BIGINT NOT NULL AUTO_INCREMENT, + value INT NOT NULL, + cond BOOL NOT NULL, + other_key BIGINT NOT NULL, + PRIMARY KEY(id), + KEY other_key (other_key) + ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci + """.execute() + + sql""" + INSERT INTO pokedex VALUES + (1, "Squirtle", "a cute water turtle"), + (2, "Wartortle", "Squirtle's more sassy evolved form"), + (3, "Blastoise", "an awesome turtle with water cannons"), + (4, "Pikachu", "an overrated electric mouse"), + (5, "Geodude", "a rock with arms"), + (6, "Jigglypuff", "whoever thought Jigglypuff would be a good idea was stupid"), + (7, "Magikarp", "some say it's worthless") + """.execute() + + sql""" + INSERT INTO pokemon VALUES + (1, 1, 4, NULL), + (2, 1, 3, 1), + (3, 5, 6, 2), + (4, 6, 2, 1), + (6, 3, 36, 1), + (7, 4, 3, NULL) + """.execute() + + sql""" + INSERT INTO professor_oaks_pokemon VALUES + (1, "Squirtle", NULL), + (2, "Bulbasaur", NULL), + (3, "Charmander", NULL) + """.execute() + + sql""" + INSERT INTO undefeated_trainers VALUES + (1, "Lass Haley"), + (2, "Youngster Jimmy"), + (3, "Gym Leader Brock") + """.execute() + + sql""" + INSERT INTO pagination VALUES + (1, 2, TRUE, 1), + (2, 1, TRUE, 1), + (3, 10, FALSE, 3), + (4, 3, TRUE, 5), + (5, 1, TRUE, 6), + (6, 2, TRUE, 9), + (7, 1, TRUE, 1), + (8, 2, FALSE, 3), + (9, 2, TRUE, 5), + (10, 3, TRUE, 2) + """.execute() + } } - val streamConnection2 = try { - DriverManager.getConnection(url + dbName, user, pass) + + def deleteDb(): Unit = withConnection { implicit connection => + sql"DROP DATABASE relate_it_tests".execute() } +} + + + +class RelateITSpec extends Specification with Db { + + override def map(tests: =>Fragments) = Step(createDb) ^ tests ^ Step(deleteDb) + + def streamConnection = DriverManager.getConnection(url + dbName, user, pass) + def streamConnection2 = DriverManager.getConnection(url + dbName, user, pass) case class PokedexEntry( id: Long, @@ -69,8 +190,8 @@ class RelateITSpec extends Specification { //check if statements all closed in all tests stmt.isClosed "insert" should { - - "work in the basic case (uses select to test)" in { + + "work in the basic case (uses select to test)" in withConnection { implicit connection => val pokemonName = "Snorlax" val pokemonDesc = "a sleepy Pokemon" @@ -91,7 +212,7 @@ class RelateITSpec extends Specification { (entries.size must_== 1) and (entries(0).name must_== pokemonName) and (entries(0).description must_== pokemonDesc) } - "work for multi-insert" in { + "work for multi-insert" in withConnection { implicit connection => val pokedexId = 8 val records = List( Pokemon(-1, pokedexId, 16, Some(1L)), @@ -115,7 +236,7 @@ class RelateITSpec extends Specification { """).on { implicit query => long("pokedexId", pokedexId) }.asList(pokemonParser) - + val levelAndTrainerIdFromDb = pokemon.map { pokemon => (pokemon.level, pokemon.trainerId) } @@ -125,7 +246,7 @@ class RelateITSpec extends Specification { (pokemon.size must_== records.size) and (levelAndTrainerIdFromDb must_== levelAndTrainerIdFromTest) } - "be able to retrieve an autogenerated key" in { + "be able to retrieve an autogenerated key" in withConnection { implicit connection => val id = SQL (""" INSERT INTO pokedex (name, description) VALUES ("Charmander", "as adorable as a fire lizard can be") @@ -133,7 +254,7 @@ class RelateITSpec extends Specification { true } - "be able to retrieve a list of autogenerated keys" in { + "be able to retrieve a list of autogenerated keys" in withConnection { implicit connection => val newEntries = Array( PokedexEntry(-1, "Bulbasaur", "a weird leaf thing grows on its back"), PokedexEntry(-1, "Ivysaur", "hard to say if it's any different from Bulbasaur") @@ -147,12 +268,12 @@ class RelateITSpec extends Specification { query.string("name", entry.name) query.string("description", entry.description) }.executeInsertLongs - + //not totally implemented yet ids.size must_== newEntries.size } - "ignore parameters not in the query" in { + "ignore parameters not in the query" in withConnection { implicit connection => val pokemonName = "Mewtwo" val pokemonDesc = "an angst filled Pokemon" @@ -174,7 +295,7 @@ class RelateITSpec extends Specification { (entries.size must_== 1) and (entries(0).name must_== pokemonName) and (entries(0).description must_== pokemonDesc) } - "fail to work if a parameter is not provided" in { + "fail to work if a parameter is not provided" in withConnection { implicit connection => def failure = SQL(""" INSERT INTO pokedex VALUES (1, {name} "a description") """).executeInsertLong @@ -182,7 +303,7 @@ class RelateITSpec extends Specification { failure must throwA[SQLException] } - "fail to work if a wrong list is provided" in { + "fail to work if a wrong list is provided" in withConnection { implicit connection => def failure = SQL(""" INSERT INTO pokedex VALUES {tuples} """).expand { implicit query => @@ -198,7 +319,7 @@ class RelateITSpec extends Specification { } "select" should { - "work with asSingle (also tests retrieving null value)" in { + "work with asSingle (also tests retrieving null value)" in withConnection { implicit connection => val pokemon = SQL(""" SELECT id, pokedex_id, level, trainer_id FROM pokemon @@ -209,8 +330,8 @@ class RelateITSpec extends Specification { (pokemon.id must_== 7) and (pokemon.pokedexId must_== 4) and (pokemon.level must_== 3) and (pokemon.trainerId must_== None) } - - "work when asSingleOption should return a value" in { + + "work when asSingleOption should return a value" in withConnection { implicit connection => val pokemon = SQL(""" SELECT id, pokedex_id, level, trainer_id FROM pokemon @@ -222,17 +343,17 @@ class RelateITSpec extends Specification { (pokemon.id must_== 7) and (pokemon.pokedexId must_== 4) and (pokemon.level must_== 3) and (pokemon.trainerId must_== None) } - "work when asSingleOption should not return a value" in { + "work when asSingleOption should not return a value" in withConnection { implicit connection => val pokemon = SQL(""" SELECT id, pokedex_id, level, trainer_id FROM pokemon WHERE id = -1 """).asSingleOption(pokemonParser) - + pokemon must_== None } - - "work with asSet" in { + + "work with asSet" in withConnection { implicit connection => val squirtle = PokedexEntry(1, "Squirtle", "a cute water turtle") val pokemon = SQL(""" @@ -246,7 +367,7 @@ class RelateITSpec extends Specification { (pokemon.size must_== 1) and (pokemon must contain(squirtle)) } - "work with empty asSet" in { + "work with empty asSet" in withConnection { implicit connection => val pokemon = SQL(""" SELECT id, name, description FROM pokedex @@ -256,10 +377,10 @@ class RelateITSpec extends Specification { pokemon.size must_== 0 } - "work with asSeq" in { + "work with asSeq" in withConnection { implicit connection => val squirtle = PokedexEntry(1, "Squirtle", "a cute water turtle") val pikachu = PokedexEntry(4, "Pikachu", "an overrated electric mouse") - + val pokemon = SQL(""" SELECT id, name, description FROM pokedex @@ -272,7 +393,7 @@ class RelateITSpec extends Specification { (pokemon.size must_== 2) and (pokemon must contain(squirtle)) and (pokemon must contain(pikachu)) } - "work with empty asSeq" in { + "work with empty asSeq" in withConnection { implicit connection => val pokemon = SQL(""" SELECT id, name, description FROM pokedex @@ -282,7 +403,7 @@ class RelateITSpec extends Specification { (pokemon.size must_== 0) } - "work with asIterable" in { + "work with asIterable" in withConnection { implicit connection => val names = Array("Wartortle", "Blastoise", "Geodude") val pokemon = SQL(""" @@ -299,7 +420,7 @@ class RelateITSpec extends Specification { (iterableAsList must contain(names(0))) and (iterableAsList must contain(names(1))) and (iterableAsList must contain(names(2))) } - "work with empty asIterable" in { + "work with empty asIterable" in withConnection { implicit connection => val pokemon = SQL(""" SELECT id, name, description FROM pokedex @@ -309,7 +430,7 @@ class RelateITSpec extends Specification { pokemon.size must_== 0 } - "work for asList" in { + "work for asList" in withConnection { implicit connection => val jigglypuff = PokedexEntry(6, "Jigglypuff", "whoever thought Jigglypuff would be a good idea was stupid") val magikarp = PokedexEntry(7, "Magikarp", "some say it's worthless") val pokemon = SQL(""" @@ -324,7 +445,7 @@ class RelateITSpec extends Specification { (pokemon.size must_== 2) and (pokemon must contain(jigglypuff)) and (pokemon must contain(magikarp)) } - "work for empty asList" in { + "work for empty asList" in withConnection { implicit connection => val pokemon = SQL(""" SELECT id, name, description FROM pokedex @@ -334,10 +455,10 @@ class RelateITSpec extends Specification { pokemon.size must_== 0 } - "work for asMap" in { + "work for asMap" in withConnection { implicit connection => val wartortle = PokedexEntry(2, "Wartortle", "Squirtle's more sassy evolved form") val blastoise = PokedexEntry(3, "Blastoise", "an awesome turtle with water cannons") - + val pokemon = SQL(""" SELECT id, name, description FROM pokedex @@ -352,7 +473,7 @@ class RelateITSpec extends Specification { (pokemon(wartortle.name) must_== wartortle.description) and (pokemon(blastoise.name) must_== blastoise.description) } - "work for empty asMap" in { + "work for empty asMap" in withConnection { implicit connection => val pokemon = SQL(""" SELECT id, name, description FROM pokedex @@ -364,7 +485,7 @@ class RelateITSpec extends Specification { pokemon.size must_== 0 } - "work for asIterator" in { + "work for asIterator" in withConnection { implicit connection => val wartortle = PokedexEntry(2, "Wartortle", "Squirtle's more sassy evolved form") val blastoise = PokedexEntry(3, "Blastoise", "an awesome turtle with water cannons") @@ -380,7 +501,7 @@ class RelateITSpec extends Specification { (pokemon.size must_== 2) and (pokemon must contain(wartortle)) and (pokemon must contain(blastoise)) } - "work for empty asIterator" in { + "work for empty asIterator" in withConnection { implicit connection => val pokemon = SQL(""" SELECT id, name, description FROM pokedex @@ -390,7 +511,7 @@ class RelateITSpec extends Specification { pokemon.size must_== 0 } - "work for the limit offset implementation of paginated" in { + "work for the limit offset implementation of paginated" in withConnection { implicit connection => val ids = List(1L, 2L, 3L) val correctPokemonNames = List("Squirtle", "Wartortle", "Blastoise") @@ -412,7 +533,7 @@ class RelateITSpec extends Specification { pokemonNames must_== correctPokemonNames } - "work for the limit offset implementation of paginated when empty" in { + "work for the limit offset implementation of paginated when empty" in withConnection { implicit connection => val pokemonNames = PaginatedQuery(pokedexParser, 2, 0) { SQL(""" SELECT id, name, description @@ -431,7 +552,7 @@ class RelateITSpec extends Specification { value: Int ) - "work for PaginatedQuery" in { + "work for PaginatedQuery" in withConnection { implicit connection => val parser = RowParser { row => Result(row.long("id"), row.int("value")) } @@ -453,8 +574,8 @@ class RelateITSpec extends Specification { sums must_== 15 } - - "work using expand for the IN clause" in { + + "work using expand for the IN clause" in withConnection { implicit connection => val ids = Array(1L, 2L, 3L) val pokemonNames = SQL(""" @@ -470,7 +591,7 @@ class RelateITSpec extends Specification { (pokemonNames must contain("Squirtle")) and (pokemonNames must contain("Wartortle")) and (pokemonNames must contain("Blastoise")) } - "fail to insert if given a select query" in { + "fail to insert if given a select query" in withConnection { implicit connection => def insertOnSelect = SQL(""" SELECT id, name, description FROM pokedex @@ -479,7 +600,7 @@ class RelateITSpec extends Specification { insertOnSelect must throwA[SQLException] } - "fail if given a list with the wrong name" in { + "fail if given a list with the wrong name" in withConnection { implicit connection => def failure = SQL(""" SELECT id, name, description FROM pokedex @@ -495,7 +616,7 @@ class RelateITSpec extends Specification { } "update" should { - "update matched rows and not update unmatched rows" in { + "update matched rows and not update unmatched rows" in withConnection { implicit connection => val correct = List( Starter(1L, "Squirtle", Some(1L)), Starter(2L, "Bulbasaur", None), @@ -521,7 +642,7 @@ class RelateITSpec extends Specification { } "delete" should { - "delete matched rows and not delete unmatched rows" in { + "delete matched rows and not delete unmatched rows" in withConnection { implicit connection => val correct = List("Lass Haley", "Youngster Jimmy") SQL(""" diff --git a/src/it/scala/com/lucidchart/open/relate/row_insertion.sql b/src/it/scala/com/lucidchart/open/relate/row_insertion.sql deleted file mode 100644 index ca2fbf2..0000000 --- a/src/it/scala/com/lucidchart/open/relate/row_insertion.sql +++ /dev/null @@ -1,52 +0,0 @@ - -USE relate_it_tests; - -TRUNCATE TABLE pokedex; -TRUNCATE TABLE pokemon; -TRUNCATE TABLE professor_oaks_pokemon; -TRUNCATE TABLE undefeated_trainers; -TRUNCATE TABLE pagination; - -#populate the pokedex -INSERT INTO pokedex VALUES - (1, "Squirtle", "a cute water turtle"), - (2, "Wartortle", "Squirtle's more sassy evolved form"), - (3, "Blastoise", "an awesome turtle with water cannons"), - (4, "Pikachu", "an overrated electric mouse"), - (5, "Geodude", "a rock with arms"), - (6, "Jigglypuff", "whoever thought Jigglypuff would be a good idea was stupid"), - (7, "Magikarp", "some say it's worthless"); - -#create some pokemon -INSERT INTO pokemon VALUES - (1, 1, 4, NULL), - (2, 1, 3, 1), - (3, 5, 6, 2), - (4, 6, 2, 1), - (6, 3, 36, 1), - (7, 4, 3, NULL); - -#create pokemon for professor oak -INSERT INTO professor_oaks_pokemon VALUES - (1, "Squirtle", NULL), - (2, "Bulbasaur", NULL), - (3, "Charmander", NULL); - -#create undefeated trainers -INSERT INTO undefeated_trainers VALUES - (1, "Lass Haley"), - (2, "Youngster Jimmy"), - (3, "Gym Leader Brock"); - -#populate pagination table -INSERT INTO pagination VALUES - (1, 2, TRUE, 1), - (2, 1, TRUE, 1), - (3, 10, FALSE, 3), - (4, 3, TRUE, 5), - (5, 1, TRUE, 6), - (6, 2, TRUE, 9), - (7, 1, TRUE, 1), - (8, 2, FALSE, 3), - (9, 2, TRUE, 5), - (10, 3, TRUE, 2); diff --git a/src/it/scala/com/lucidchart/open/relate/setup.sql b/src/it/scala/com/lucidchart/open/relate/setup.sql deleted file mode 100644 index a958cbd..0000000 --- a/src/it/scala/com/lucidchart/open/relate/setup.sql +++ /dev/null @@ -1,48 +0,0 @@ - -CREATE DATABASE relate_it_tests; -USE relate_it_tests; - -#create a table with an auto incremented bigint id -CREATE TABLE pokedex ( - id BIGINT NOT NULL AUTO_INCREMENT, - name VARCHAR(50) NOT NULL, - description VARCHAR(200) NOT NULL, - PRIMARY KEY (id), - KEY name_key (name) -) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; - -#create a table with nullable fields -CREATE TABLE pokemon ( - id BIGINT NOT NULL AUTO_INCREMENT, - pokedex_id BIGINT NOT NULL, - level INT NOT NULL, - trainer_id BIGINT, - PRIMARY KEY(id), - KEY trainer_key (trainer_id) -) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; - -#create a table that will be used for updating -CREATE TABLE professor_oaks_pokemon ( - id BIGINT NOT NULL AUTO_INCREMENT, - name VARCHAR(50) NOT NULL, - trainer_id BIGINT, - PRIMARY KEY(id), - KEY trainer_key (trainer_id) -) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; - -#create a table that will be used for deleting -CREATE TABLE undefeated_trainers ( - id BIGINT NOT NULL AUTO_INCREMENT, - name VARCHAR(50) NOT NULL, - PRIMARY KEY(id) -) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; - -#create a table for pagination -CREATE TABLE pagination ( - id BIGINT NOT NULL AUTO_INCREMENT, - value INT NOT NULL, - cond BOOL NOT NULL, - other_key BIGINT NOT NULL, - PRIMARY KEY(id), - KEY other_key (other_key) -) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;