diff --git a/README.md b/README.md
index 9cb7b11..dcca511 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-install the specs-lib using maven,
+install the conifers-specs using maven,
```
mvn clean install
@@ -10,8 +10,8 @@ Then use as a dependency
```
com.specs
- specs-lib
- 1.0-SNAPSHOT
+ conifers-specs
+ 1.0
```
@@ -67,15 +67,15 @@ class CustomerOrderComponentSpecs extends ComponentSpecs {
//beforeAll start a database server
//afterAll stop the database server
- scenario("when customer order is put") {
- Given("a order")
+ scenario("successful customer order") {
+ Given("an order")
val order = new CustomerOrder(List(Item("Skateboard")))
When("order is checked out")
order.checkout()
- Then("should be ready")
- assert(order.state == "READY")
+ Then("should be ready to be shipped")
+ assert(order.state == "READY TO BE SHIPPED")
//maybe I want to test its state in database as well
//more granular assertions than FlowSpecs
}
@@ -87,7 +87,10 @@ class CustomerOrderComponentSpecs extends ComponentSpecs {
----------
```
-System testing is testing conducted on a complete, integrated system to evaluate the system's compliance with its specified requirements. System testing falls within the scope of black-box testing, and as such, should require no knowledge of the inner design of the code or logic.
+System testing is testing conducted on a complete, integrated system to
+evaluate the system's compliance with its specified requirements.
+System testing falls within the scope of black-box testing, and as such,
+should require no knowledge of the inner design of the code or logic.
```
```
diff --git a/pom.xml b/pom.xml
index 56ebdc7..343b9e7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,8 +3,8 @@
4.0.0
com.specs
- specs-lib
- 1.0-SNAPSHOT
+ conifers-specs
+ 1.0
jar
UCF-specs-lib
@@ -23,6 +23,13 @@
compile
+
+ org.json
+ json
+ 20160810
+ compile
+
+
org.scala-lang
scala-library
@@ -72,6 +79,26 @@
compile
+
+ io.gatling.highcharts
+ gatling-charts-highcharts
+ 2.0.0
+ compile
+
+
+ ch.qos.logback
+ logback-classic
+
+
+
+
+
+ commons-dbcp
+ commons-dbcp
+ 1.4
+ compile
+
+
@@ -122,6 +149,22 @@
+
+ io.gatling
+ gatling-maven-plugin
+ 2.0.0
+
+
+ -Durl=http://localhost:9000
+ -DnumberOfUsers=10
+ -DnumberOfRepetitions=1
+ -DdurationMinutes=1
+ -DpauseBetweenRequestsMs=3000
+ -Ddebug=true
+
+
+
+
diff --git a/src/main/scala/com/specs/AsyncFlowSpecs.scala b/src/main/scala/com/specs/AsyncFlowSpecs.scala
index 2ed9abd..30fea34 100644
--- a/src/main/scala/com/specs/AsyncFlowSpecs.scala
+++ b/src/main/scala/com/specs/AsyncFlowSpecs.scala
@@ -1,12 +1,12 @@
package com.specs
-import org.scalatest.{AsyncFeatureSpec, BeforeAndAfterAll, GivenWhenThen}
+import org.scalatest.{AsyncFeatureSpec, BeforeAndAfterAll, GivenWhenThen, Matchers}
/**
* Created by prayagupd
* on 2/15/17.
*/
-class AsyncFlowSpecs extends AsyncFeatureSpec with GivenWhenThen with BeforeAndAfterAll {
+class AsyncFlowSpecs extends AsyncFeatureSpec with GivenWhenThen with BeforeAndAfterAll with Matchers {
}
diff --git a/src/main/scala/com/specs/ComponentSpecs.scala b/src/main/scala/com/specs/ComponentSpecs.scala
index ea23391..067ea59 100644
--- a/src/main/scala/com/specs/ComponentSpecs.scala
+++ b/src/main/scala/com/specs/ComponentSpecs.scala
@@ -1,12 +1,12 @@
package com.specs
-import org.scalatest.{BeforeAndAfterEach, FeatureSpec, GivenWhenThen}
+import org.scalatest._
/**
* Created by prayagupd
* on 2/15/17.
*/
-class ComponentSpecs extends FeatureSpec with GivenWhenThen with BeforeAndAfterEach {
+trait ComponentSpecs extends FeatureSpec with GivenWhenThen with BeforeAndAfterEach with BeforeAndAfterAll with Matchers {
-}
\ No newline at end of file
+}
diff --git a/src/main/scala/com/specs/FlowSpecs.scala b/src/main/scala/com/specs/FlowSpecs.scala
index 4df6898..be510bb 100644
--- a/src/main/scala/com/specs/FlowSpecs.scala
+++ b/src/main/scala/com/specs/FlowSpecs.scala
@@ -1,12 +1,12 @@
package com.specs
-import org.scalatest.{AsyncFeatureSpec, BeforeAndAfterAll, FeatureSpec, GivenWhenThen}
+import org.scalatest.{BeforeAndAfterAll, FeatureSpec, GivenWhenThen, Matchers}
/**
* Created by prayagupd
* on 2/15/17.
*/
-class FlowSpecs extends AsyncFeatureSpec with GivenWhenThen with BeforeAndAfterAll {
+trait FlowSpecs extends FeatureSpec with GivenWhenThen with BeforeAndAfterAll with Matchers {
}
diff --git a/src/main/scala/com/specs/UnitSpecs.scala b/src/main/scala/com/specs/UnitSpecs.scala
index b364d6a..62d2a8f 100644
--- a/src/main/scala/com/specs/UnitSpecs.scala
+++ b/src/main/scala/com/specs/UnitSpecs.scala
@@ -1,13 +1,13 @@
package com.specs
import org.scalamock.scalatest.MockFactory
-import org.scalatest.FunSpec
+import org.scalatest.{FunSpec, Matchers}
/**
* Created by prayagupd
* on 2/15/17.
*/
-abstract class UnitSpecs extends FunSpec with MockFactory {
+abstract class UnitSpecs extends FunSpec with MockFactory with Matchers {
}
diff --git a/src/main/scala/com/specs/config/ConfigLoader.scala b/src/main/scala/com/specs/config/ConfigLoader.scala
new file mode 100644
index 0000000..b473886
--- /dev/null
+++ b/src/main/scala/com/specs/config/ConfigLoader.scala
@@ -0,0 +1,41 @@
+package com.specs.config
+
+import java.util.Properties
+
+import sys.process._
+import scala.language.postfixOps
+
+/**
+ * Created by prayagupd
+ * on 4/4/17.
+ */
+class ConfigLoader {
+
+ var appConfig: Properties = new Properties() {
+ load(ConfigLoader.this.getClass.getClassLoader.getResourceAsStream(config))
+ }
+
+ def environment: String = {
+
+ Option(System.getProperty("CI_APPLICATION_ENVIRONMENT")) match {
+ case Some(env) =>
+ println("-DCI_APPLICATION_ENVIRONMENT")
+ println(s"application CI environment is set to $env")
+ env
+ case None =>
+ println("============ infra environment ============")
+ println("env"!!)
+ println("============ infra environment ============")
+ println(s"application environment is set to ${System.getenv("APPLICATION_ENVIRONMENT")}")
+ System.getenv("APPLICATION_ENVIRONMENT")
+ }
+ }
+
+ def config: String = {
+ if (environment != null && configExists(environment)) return "application-" + environment + ".properties"
+ "application.properties"
+ }
+
+ private def configExists(env: String): Boolean =
+ classOf[ConfigLoader].getClassLoader.getResource("application-" + env + ".properties") != null
+}
diff --git a/src/main/scala/com/specs/database/DatabaseComponentSpecs.scala b/src/main/scala/com/specs/database/DatabaseComponentSpecs.scala
new file mode 100644
index 0000000..7271137
--- /dev/null
+++ b/src/main/scala/com/specs/database/DatabaseComponentSpecs.scala
@@ -0,0 +1,163 @@
+package com.specs.database
+
+import java.sql._
+
+import com.specs.ComponentSpecs
+import com.specs.config.ConfigLoader
+import org.apache.commons.dbcp.BasicDataSource
+import org.json.JSONObject
+
+/**
+ * Created by prayagupd
+ * on 3/20/17.
+ */
+
+trait DatabaseComponentSpecs extends ComponentSpecs {
+
+ val appConfig = new ConfigLoader().appConfig
+
+ val url: String = appConfig.getProperty("state.url")
+ val database: String = appConfig.getProperty("state.database.name")
+ val user: String = appConfig.getProperty("state.username")
+ val password: String = appConfig.getProperty("state.password")
+
+ val establishedConnections = connectionPool()
+
+ def queryState(query: String, numberOfColumns: Int): java.util.List[JSONObject] = {
+ var statement: Statement = null
+ var resultSet: ResultSet = null
+ val states: java.util.List[JSONObject] = new java.util.ArrayList[JSONObject]
+ try {
+ val connection: Connection = getEstablishedDatabaseConnection
+ connection.setAutoCommit(false)
+ statement = connection.createStatement
+ val start: Long = System.currentTimeMillis
+ resultSet = statement.executeQuery(query)
+ val columns: ResultSetMetaData = resultSet.getMetaData
+ while (resultSet.next) {
+ val jsonObject: JSONObject = new JSONObject
+ Range(1, numberOfColumns).foreach(col => {
+ try {
+ jsonObject.put(columns.getColumnName(col), resultSet.getString(col));
+ } catch {
+ case e: SQLException => e.printStackTrace()
+ }
+ })
+ states.add(jsonObject)
+ }
+ System.out.println("read :: timeTaken to read = " + (System.currentTimeMillis - start) + "ms")
+ resultSet.close()
+ statement.close()
+ connection.commit()
+ connection.close()
+ return states
+
+ } catch {
+ case ex: SQLException => {
+ System.err.println("SQLException information")
+ while (ex != null) {
+ System.err.println("Error msg: " + ex.getMessage)
+ val ex1 = ex.getNextException
+ }
+ }
+ }
+ states
+ }
+
+ def connectionPool() : BasicDataSource = {
+ println(s"setting up connection pool for $url")
+ val driver: String = appConfig.getProperty("state.database.driver")
+ val autoCommit: Boolean = appConfig.getOrDefault("state.database.auto.commit", "true").toString.toBoolean
+
+ val establishedConnections = new BasicDataSource()
+ establishedConnections.setUrl(url)
+ establishedConnections.setUsername(user)
+ establishedConnections.setPassword(password)
+ establishedConnections.setDriverClassName(driver)
+
+ establishedConnections.setMinIdle(5)
+ establishedConnections.setMaxIdle(10)
+ establishedConnections.setMaxOpenPreparedStatements(50)
+ establishedConnections.setInitialSize(5)
+ establishedConnections.setPoolPreparedStatements(true)
+ establishedConnections.setDefaultAutoCommit(autoCommit); //adds ~30ms, on connection creation delay
+ establishedConnections.getConnection.close()
+
+ println("Physical connection pool is setup for " + establishedConnections.getValidationQuery)
+ establishedConnections
+ }
+
+ def readState(databaseName: String, tableName: String): java.util.List[String] = {
+ var statement: Statement = null
+ var resultSet: ResultSet = null
+ val states: java.util.List[String] = new java.util.ArrayList[String]
+ try {
+ val connection: Connection = getEstablishedDatabaseConnection
+ connection.setAutoCommit(false)
+ statement = connection.createStatement
+ val start: Long = System.currentTimeMillis
+ resultSet = statement.executeQuery("SELECT * FROM " + databaseName + "." + tableName)
+ System.out.println("read :: timeTaken to read = " + (System.currentTimeMillis - start) + "ms")
+ while (resultSet.next) {
+ Range(1, 16).foreach(x => {
+ try {
+ System.out.print(resultSet.getString(x) + ",");
+ } catch {
+ case e: SQLException => e.printStackTrace()
+ }
+ })
+ System.out.println("\n")
+ states.add(resultSet.getString(1))
+ }
+ resultSet.close()
+ statement.close()
+ connection.commit()
+
+ println("readState :: closing connection")
+ connection.close()
+
+ } catch {
+ case ex: SQLException => {
+ System.err.println("readState :: SQLException error")
+ while (ex != null) {
+ System.err.println("Error msg: " + ex.getMessage)
+ val ex1 = ex.getNextException
+ }
+ }
+ }
+ states
+ }
+
+ def dropRecords(table: String) {
+ var statement: Statement = null
+ try {
+ val connection: Connection = getEstablishedDatabaseConnection
+ connection.setAutoCommit(true)
+ val compiledQuery: String = "DELETE FROM " + table + " where 1=1"
+ statement = connection.createStatement
+ val start: Long = System.currentTimeMillis
+ statement.executeUpdate(compiledQuery)
+ val end: Long = System.currentTimeMillis
+ System.out.println("drop :: total time taken = " + (end - start) + " ms")
+ statement.close()
+
+ println("dropRecords :: closing connection")
+ connection.close()
+
+ } catch {
+ case ex: SQLException => {
+ System.err.println("dropRecords :: SQLException information")
+ while (ex != null) {
+ System.err.println("Error msg: " + ex.getMessage)
+ val ex1 = ex.getNextException
+ System.exit(0)
+ }
+ }
+ }
+ }
+
+ @throws[SQLException]
+ protected def getEstablishedDatabaseConnection: Connection = {
+ establishedConnections.getConnection
+ }
+}
diff --git a/src/main/scala/com/specs/end2end/SiahlSpecs.scala b/src/main/scala/com/specs/end2end/SiahlSpecs.scala
new file mode 100644
index 0000000..ea63112
--- /dev/null
+++ b/src/main/scala/com/specs/end2end/SiahlSpecs.scala
@@ -0,0 +1,13 @@
+package com.specs.end2end
+
+import com.specs.database.DatabaseComponentSpecs
+import com.specs.http.HttpFlowSpecs
+
+/**
+ * Created by prayagupd
+ * on 3/24/17.
+ */
+
+trait SiahlSpecs extends HttpFlowSpecs with DatabaseComponentSpecs {
+
+}
diff --git a/src/main/scala/com/specs/http/HttpFlowSpecs.scala b/src/main/scala/com/specs/http/HttpFlowSpecs.scala
index 03b6ade..e76e9d9 100644
--- a/src/main/scala/com/specs/http/HttpFlowSpecs.scala
+++ b/src/main/scala/com/specs/http/HttpFlowSpecs.scala
@@ -13,10 +13,11 @@ import org.apache.http.impl.client.DefaultHttpClient
* on 3/4/17.
*/
-class HttpFlowSpecs extends FlowSpecs {
+trait HttpFlowSpecs extends FlowSpecs {
def doHttpGet(endpoint: String): CloseableHttpResponse = {
val httpRequest = new HttpGet(endpoint)
+ println(s"curl -XGET ${endpoint}")
val response = (new DefaultHttpClient).execute(httpRequest)
response
}
@@ -26,7 +27,11 @@ class HttpFlowSpecs extends FlowSpecs {
httpRequest.setHeader("Content-type", contentType)
httpRequest.setEntity(new StringEntity(content))
+ val contentTypo = s"Content-Type: $contentType"
+ println(s"curl -H $contentTypo -XPOST -d '${content}' ${endpoint}")
+
val response = (new DefaultHttpClient).execute(httpRequest)
+ println("http response :: " + response )
response
}
@@ -34,7 +39,7 @@ class HttpFlowSpecs extends FlowSpecs {
val responseBody: String = new BufferedReader(new InputStreamReader(response.getEntity.getContent))
.lines().collect(Collectors.joining("\n"))
- println("Response body = " + responseBody)
+ println("Http Response body = " + responseBody)
responseBody
}
}
diff --git a/src/main/scala/com/specs/tags/E2ETagged.scala b/src/main/scala/com/specs/tags/E2ETagged.scala
new file mode 100644
index 0000000..a6c3dc2
--- /dev/null
+++ b/src/main/scala/com/specs/tags/E2ETagged.scala
@@ -0,0 +1,12 @@
+package com.specs.tags
+
+import org.scalatest.Tag
+
+/**
+ * Created by prayagupd
+ * on 3/27/17.
+ */
+
+object E2ETagged extends Tag(name = "e2e") {
+
+}
diff --git a/src/main/scala/com/specs/tags/PerfTagged.scala b/src/main/scala/com/specs/tags/PerfTagged.scala
new file mode 100644
index 0000000..79cf14d
--- /dev/null
+++ b/src/main/scala/com/specs/tags/PerfTagged.scala
@@ -0,0 +1,12 @@
+package com.specs.tags
+
+import org.scalatest.Tag
+
+/**
+ * Created by prayagupd
+ * on 3/27/17.
+ */
+
+object PerfTagged extends Tag(name = "perf") {
+
+}
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
new file mode 100644
index 0000000..e69de29
diff --git a/src/test/scala/com/specs/CustomerOrder.scala b/src/test/scala/com/specs/CustomerOrder.scala
index 7e3e598..8a07f60 100644
--- a/src/test/scala/com/specs/CustomerOrder.scala
+++ b/src/test/scala/com/specs/CustomerOrder.scala
@@ -14,4 +14,3 @@ class CustomerOrder(items: List[Item]) {
}
case class Item(name: String)
-
diff --git a/src/test/scala/com/specs/CustomerOrderComponentSpecs.scala b/src/test/scala/com/specs/CustomerOrderComponentSpecs.scala
index 5d02f9a..901c353 100644
--- a/src/test/scala/com/specs/CustomerOrderComponentSpecs.scala
+++ b/src/test/scala/com/specs/CustomerOrderComponentSpecs.scala
@@ -17,7 +17,7 @@ class CustomerOrderComponentSpecs extends ComponentSpecs {
order.checkout()
Then("should be ready")
- assert(order.state == "READY")
+ order.state shouldBe "READY"
//maybe I want to test its state in database as well
//more granular assertions than FlowSpecs
}
diff --git a/src/test/scala/com/specs/CustomerOrderFlowSpecs.scala b/src/test/scala/com/specs/CustomerOrderFlowSpecs.scala
index 6a2389b..5cc632d 100644
--- a/src/test/scala/com/specs/CustomerOrderFlowSpecs.scala
+++ b/src/test/scala/com/specs/CustomerOrderFlowSpecs.scala
@@ -18,7 +18,7 @@ class CustomerOrderFlowSpecs extends FlowSpecs {
customerOrder.checkout()
Then("My order should be ready")
- assert(customerOrder.state == "READY")
+ customerOrder.state shouldBe "READY"
}
}
diff --git a/src/test/scala/com/specs/SomeUnitSpecs.scala b/src/test/scala/com/specs/SomeUnitSpecs.scala
index 328fa06..c3f6fe6 100644
--- a/src/test/scala/com/specs/SomeUnitSpecs.scala
+++ b/src/test/scala/com/specs/SomeUnitSpecs.scala
@@ -12,7 +12,7 @@ class SomeUnitSpecs extends UnitSpecs {
val subject = new Subject()
val response = subject.doSomething("event")
- assert(response == "Processing event")
+ response shouldBe "Processing event"
}
}
}
diff --git a/src/test/scala/com/specs/config/ConfigLoaderUnitSpecs.scala b/src/test/scala/com/specs/config/ConfigLoaderUnitSpecs.scala
new file mode 100644
index 0000000..d0a80a5
--- /dev/null
+++ b/src/test/scala/com/specs/config/ConfigLoaderUnitSpecs.scala
@@ -0,0 +1,22 @@
+package com.specs.config
+
+import java.util.Properties
+
+import org.scalatest.{FunSuite, Matchers}
+
+/**
+ * Created by prayagupd
+ * on 6/9/17.
+ */
+
+class ConfigLoaderUnitSpecs extends FunSuite with Matchers {
+
+ test("returns environment if theres APPLICATION_ENVIRONMENT set as argLine") {
+
+ val configLoader = new ConfigLoader
+ configLoader.appConfig = new Properties()
+
+ configLoader.environment should not be empty
+
+ }
+}
diff --git a/src/test/scala/com/specs/flow/http/AsyncSomeHttpFlowSpecs.scala b/src/test/scala/com/specs/flow/http/AsyncSomeHttpFlowSpecs.scala
index 4b2eea5..c237d16 100644
--- a/src/test/scala/com/specs/flow/http/AsyncSomeHttpFlowSpecs.scala
+++ b/src/test/scala/com/specs/flow/http/AsyncSomeHttpFlowSpecs.scala
@@ -42,7 +42,7 @@ class AsyncSomeHttpFlowSpecs extends AsyncHttpFlowSpecs with Informing {
println(s"After assertion ${json}")
}
}
- assert(response.status == StatusCode.int2StatusCode(200))
+ response.status shouldBe StatusCode.int2StatusCode(200)
}
}
}
diff --git a/src/test/scala/com/specs/flow/http/SomeHttpFlowSpecs.scala b/src/test/scala/com/specs/flow/http/SomeHttpFlowSpecs.scala
index 548bb1c..4df96aa 100644
--- a/src/test/scala/com/specs/flow/http/SomeHttpFlowSpecs.scala
+++ b/src/test/scala/com/specs/flow/http/SomeHttpFlowSpecs.scala
@@ -13,7 +13,7 @@ class SomeHttpFlowSpecs extends HttpFlowSpecs {
feature("Getting user posts on my API server") {
- scenario("As a software engineer, I want to receive the user posts when I call the endpoint") {
+ ignore("As a software engineer, I want to receive the user posts when I call the endpoint") {
When("I send a GET request to the http endpoint")
val response = doHttpGet("https://jsonplaceholder.typicode.com/posts/1")
@@ -31,7 +31,7 @@ class SomeHttpFlowSpecs extends HttpFlowSpecs {
|}
""".stripMargin
- assert(JSON.parseRaw(responseContent(response)) == JSON.parseRaw(expectedJson))
+ JSON.parseRaw(responseContent(response)) shouldBe JSON.parseRaw(expectedJson)
}
}
}