-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* moved the code * added code description and enhanced `README.md` * fixed for Scala 2.13 --------- Co-authored-by: miroslavpojer <miroslav.pojer@absa.africa>
- Loading branch information
1 parent
3d274b3
commit 8778d5f
Showing
21 changed files
with
1,358 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# | ||
# Copyright 2023 ABSA Group 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. | ||
|
||
# top-most EditorConfig file | ||
root = true | ||
|
||
[*] | ||
charset = utf-8 | ||
end_of_line = lf | ||
trim_trailing_whitespace = true | ||
|
||
[*.{java,scala,js,json,css}] | ||
indent_size = 2 | ||
indent_style = space | ||
insert_final_newline = true | ||
max_line_length = 120 | ||
|
||
[*.md] | ||
trim_trailing_whitespace = false | ||
|
||
[*.{cmd,bat}] | ||
end_of_line = crlf | ||
insert_final_newline = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# | ||
# Copyright 2023 ABSA Group 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. | ||
|
||
############################### | ||
# Git Line Endings # | ||
############################### | ||
|
||
# Set default behaviour to automatically normalize line endings. | ||
* text=auto | ||
|
||
# Force the following filetypes to have unix eols, Windows can usually handle it well | ||
*.* text eol=lf | ||
|
||
# Force batch scripts to always use CRLF line endings as they in some cases might not work correctly. | ||
# Also if a repo is accessed in Windows via a file share from Linux, the scripts will work too | ||
*.cmd text eol=crlf | ||
*.bat text eol=crlf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# | ||
# Copyright 2023 ABSA Group 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. | ||
# | ||
# use glob syntax. | ||
syntax: glob | ||
*.ser | ||
*.class | ||
*~ | ||
*.bak | ||
#*.off | ||
*.old | ||
|
||
# eclipse conf file | ||
.settings | ||
.classpath | ||
.project | ||
.manager | ||
.scala_dependencies | ||
.scalastyle | ||
|
||
# idea | ||
.idea | ||
*.iml | ||
|
||
# vs code | ||
.vscode | ||
|
||
# building | ||
target | ||
build | ||
null | ||
tmp* | ||
temp* | ||
dist | ||
test-output | ||
build.log | ||
|
||
# other scm | ||
.svn | ||
.CVS | ||
.hg* | ||
|
||
.bsp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,22 @@ | ||
# balta | ||
# Balta | ||
|
||
Scala library to write Postgres DB code tests with | ||
|
||
Balta is a Scala library to help creating database tests, particularly testing Database functions. It is based on the | ||
popular [ScalaTest](http://www.scalatest.org/) library and uses [PostgreSQL](https://www.postgresql.org/) as the | ||
database engine. | ||
|
||
It's a natural complement to the use of [Fa-Db library](https://github.com/AbsaOSS/fa-db) in applications. | ||
|
||
## Expected test-case structure | ||
1. _Transaction start_* | ||
2. Insert needed data into tables | ||
3. Call the function to be tested | ||
4. Verify the return values of the function via the `verify` function provided | ||
5. Verify the data un the tables | ||
6. _Transaction rollback_* | ||
|
||
* The transaction start and rollback are done automatically before or after the execution respectively of the `test` function provided | ||
|
||
Advantages of this approach is that the tests repeateble, they are isolated from each other and the database is always | ||
in a known state before and after each test. |
172 changes: 172 additions & 0 deletions
172
balta/src/main/scala/za/co/absa/balta/DBTestSuite.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
/* | ||
* Copyright 2023 ABSA Group 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 za.co.absa.balta | ||
|
||
import org.scalactic.source | ||
import org.scalatest.Tag | ||
import org.scalatest.funsuite.AnyFunSuite | ||
import za.co.absa.balta.classes.DBFunction.DBFunctionWithPositionedParamsOnly | ||
import za.co.absa.balta.classes.setter.{AllowedParamTypes, Params} | ||
import za.co.absa.balta.classes.setter.Params.{NamedParams, OrderedParams} | ||
import za.co.absa.balta.classes.{ConnectionInfo, DBConnection, DBFunction, DBTable, QueryResult} | ||
|
||
import java.sql.DriverManager | ||
import java.time.OffsetDateTime | ||
import java.util.Properties | ||
|
||
/** | ||
* This is a base class for all DB tests. It inherits from AnyFunSuite and provides the following: | ||
* * automatic creation and provision of a DB connection | ||
* * an enhanced test function that automatically rolls back the transaction after the test is finished | ||
* * easy access to DB tables and functions | ||
* * the now() function that returns the current transaction time in the DB | ||
*/ | ||
abstract class DBTestSuite extends AnyFunSuite { | ||
|
||
/* the DB connection is ``lazy`, so it actually can be created only when needed and therefore the credentials | ||
overridden in the successor */ | ||
protected lazy implicit val dbConnection: DBConnection = { | ||
createConnection( | ||
connectionInfo.dbUrl, | ||
connectionInfo.username, | ||
connectionInfo.password | ||
) | ||
} | ||
|
||
/** | ||
* This is the connection info for the DB. It can be overridden in the derived classes to provide specific credentials | ||
*/ | ||
protected lazy val connectionInfo: ConnectionInfo = readConnectionInfoFromConfig | ||
|
||
/** | ||
* This is an enhanced test function that automatically rolls back the transaction after the test is finished | ||
* | ||
* @param testName – the name of the test | ||
* @param testTags – the optional list of tags for this test | ||
* @param testFun – the test function | ||
*/ | ||
override protected def test(testName: String, testTags: Tag*) | ||
(testFun: => Any /* Assertion */) | ||
(implicit pos: source.Position): Unit = { | ||
val dbTestFun = { | ||
try { | ||
testFun | ||
} | ||
finally { | ||
if (connectionInfo.persistData) { | ||
dbConnection.connection.commit() | ||
} else { | ||
dbConnection.connection.rollback() | ||
} | ||
} | ||
} | ||
super.test(testName, testTags: _*)(dbTestFun) | ||
} | ||
|
||
/** | ||
* This is a helper function that allows to easily access a DB table | ||
* @param tableName - the name of the table | ||
* @return - the DBTable object | ||
*/ | ||
protected def table(tableName: String): DBTable = { | ||
DBTable(tableName) | ||
} | ||
|
||
/** | ||
* This is a helper function that allows to easily access a DB function | ||
* @param functionName - the name of the function | ||
* @return - the DBFunction object | ||
*/ | ||
protected def function(functionName: String): DBFunctionWithPositionedParamsOnly = { | ||
DBFunction(functionName) | ||
} | ||
|
||
/** | ||
* This is a helper function that allows to easily get the DB current time | ||
* @param connection - the DB connection | ||
* @return - the current transaction time | ||
*/ | ||
protected def now()(implicit connection: DBConnection): OffsetDateTime = { | ||
val preparedStatement = connection.connection.prepareStatement("SELECT now() AS now") | ||
val prep = preparedStatement.executeQuery() | ||
val result = new QueryResult(prep).next().getOffsetDateTime("now").get | ||
prep.close() | ||
result | ||
} | ||
|
||
/** | ||
* This is a helper function that allows to easily create parameter for table and function queries | ||
* | ||
* @param paramName - the name of the parameter | ||
* @param value - the value of the parameter | ||
* @tparam T - the type of the parameter value | ||
* @return - a list parameters to be used in an SQL prepared statement | ||
*/ | ||
protected def add[T: AllowedParamTypes](paramName: String, value: T): NamedParams = { | ||
Params.add(paramName, value) | ||
} | ||
|
||
/** | ||
* This is a helper function that allows to easily create parameter of value NULL for table and function queries | ||
* | ||
* @param paramName - the name of the parameter | ||
* @return - a list parameters to be used in an SQL prepared statement | ||
*/ | ||
protected def addNull(paramName: String): NamedParams = { | ||
Params.addNull(paramName) | ||
} | ||
|
||
/** | ||
* This is a helper function that allows to easily create a positioned parameter for table and function queries | ||
* | ||
* @param value - the value of the parameter | ||
* @tparam T - the type of the parameter value | ||
* @return - a list parameters to be used in an SQL prepared statement | ||
*/ | ||
protected def add[T: AllowedParamTypes](value: T): OrderedParams = { | ||
Params.add(value) | ||
} | ||
|
||
/** | ||
* This is a helper function that allows to easily create a positioned parameter of value NULL for table and function queries | ||
* | ||
* @tparam T - the type of the parameter value | ||
* @return - a list parameters to be used in an SQL prepared statement | ||
*/ | ||
protected def addNull[T: AllowedParamTypes](): OrderedParams = { | ||
Params.addNull() | ||
} | ||
|
||
// private functions | ||
private def createConnection(url: String, username: String, password: String): DBConnection = { | ||
val conn = DriverManager.getConnection(url, username, password) | ||
conn.setAutoCommit(false) | ||
new DBConnection(conn) | ||
} | ||
|
||
private def readConnectionInfoFromConfig = { | ||
val properties = new Properties() | ||
properties.load(getClass.getResourceAsStream("/database.properties")) | ||
|
||
ConnectionInfo( | ||
dbUrl = properties.getProperty("test.jdbc.url"), | ||
username = properties.getProperty("test.jdbc.username"), | ||
password = properties.getProperty("test.jdbc.password"), | ||
persistData = properties.getProperty("test.persist.db", "false").toBoolean | ||
) | ||
} | ||
} |
Oops, something went wrong.