Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add database specs #1

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

install the specs-lib using maven,
install the conifers-specs using maven,

```
mvn clean install
Expand All @@ -10,8 +10,8 @@ Then use as a dependency
```
<dependency>
<groupId>com.specs</groupId>
<artifactId>specs-lib</artifactId>
<version>1.0-SNAPSHOT</version>
<artifactId>conifers-specs</artifactId>
<version>1.0</version>
</dependency>
```

Expand Down Expand Up @@ -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
}
Expand All @@ -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.
```

```
Expand Down
47 changes: 45 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<modelVersion>4.0.0</modelVersion>

<groupId>com.specs</groupId>
<artifactId>specs-lib</artifactId>
<version>1.0-SNAPSHOT</version>
<artifactId>conifers-specs</artifactId>
<version>1.0</version>
<packaging>jar</packaging>

<name>UCF-specs-lib</name>
Expand All @@ -23,6 +23,13 @@
<scope>compile</scope>
</dependency>

<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160810</version>
<scope>compile</scope>
</dependency>

<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
Expand Down Expand Up @@ -72,6 +79,26 @@
<scope>compile</scope>
</dependency>

<dependency>
<groupId>io.gatling.highcharts</groupId>
<artifactId>gatling-charts-highcharts</artifactId>
<version>2.0.0</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
<scope>compile</scope>
</dependency>

</dependencies>

<build>
Expand Down Expand Up @@ -122,6 +149,22 @@
</executions>
</plugin>

<plugin>
<groupId>io.gatling</groupId>
<artifactId>gatling-maven-plugin</artifactId>
<version>2.0.0</version>
<configuration>
<jvmArgs>
<jvmArg>-Durl=http://localhost:9000</jvmArg>
<jvmArg>-DnumberOfUsers=10</jvmArg>
<jvmArg>-DnumberOfRepetitions=1</jvmArg>
<jvmArg>-DdurationMinutes=1</jvmArg>
<jvmArg>-DpauseBetweenRequestsMs=3000</jvmArg>
<jvmArg>-Ddebug=true</jvmArg>
</jvmArgs>
</configuration>
</plugin>

</plugins>
</build>
</project>
4 changes: 2 additions & 2 deletions src/main/scala/com/specs/AsyncFlowSpecs.scala
Original file line number Diff line number Diff line change
@@ -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 {

}
6 changes: 3 additions & 3 deletions src/main/scala/com/specs/ComponentSpecs.scala
Original file line number Diff line number Diff line change
@@ -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 {

}
}
4 changes: 2 additions & 2 deletions src/main/scala/com/specs/FlowSpecs.scala
Original file line number Diff line number Diff line change
@@ -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 {

}
4 changes: 2 additions & 2 deletions src/main/scala/com/specs/UnitSpecs.scala
Original file line number Diff line number Diff line change
@@ -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 {

}
41 changes: 41 additions & 0 deletions src/main/scala/com/specs/config/ConfigLoader.scala
Original file line number Diff line number Diff line change
@@ -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
}
163 changes: 163 additions & 0 deletions src/main/scala/com/specs/database/DatabaseComponentSpecs.scala
Original file line number Diff line number Diff line change
@@ -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
}
}
Loading