Skip to content

Commit

Permalink
* Fix - multiline strings review note.
Browse files Browse the repository at this point in the history
* Fix - not used method parameters review note.
* Fix - String to Enum
* Fix - replace boolean return values in XYZResponseAction methods.
  • Loading branch information
miroslavpojer committed Sep 21, 2023
1 parent 6032a64 commit c203ab6
Show file tree
Hide file tree
Showing 33 changed files with 628 additions and 564 deletions.
23 changes: 15 additions & 8 deletions testApi/src/main/scala/africa/absa/testing/scapi/Exceptions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,30 @@ import com.networknt.schema.ValidationMessage

import scala.collection.mutable

case class UndefinedConstantsInProperties(undefinedConstants: Set[String], source: String)
case class UndefinedConstantsInPropertiesException(undefinedConstants: Set[String], source: String)
extends Exception(s"Undefined constant(s): '${undefinedConstants.mkString(", ")}' in '$source'.")

case class PropertyNotFound(property: String) extends Exception(s"Property not found: '$property'.")
case class PropertyNotFoundException(property: String) extends Exception(s"Property not found: '$property'.")

case class JsonInvalidSchema(filePath: String, messages: mutable.Set[ValidationMessage])
case class JsonInvalidSchemaException(filePath: String, messages: mutable.Set[ValidationMessage])
extends Exception(s"Json file '$filePath' not valid to defined json schema. " + messages.mkString("\n"))

case class ProjectLoadFailed() extends Exception("Problems during project loading.")
case class ProjectLoadFailedException() extends Exception("Problems during project loading.")

case class SuiteLoadFailed(detail: String) extends Exception(s"Problems during project loading. Details: $detail")
case class SuiteLoadFailedException(detail: String)
extends Exception(s"Problems during project loading. Details: $detail")

case class UndefinedHeaderType(undefinedType: String)
case class SuiteBeforeFailedException(detail: String)
extends Exception(s"Problems during running before suite logic. Details: $detail")

case class UndefinedHeaderTypeException(undefinedType: String)
extends Exception(s"Undefined Header content type: '$undefinedType'")

case class UndefinedResponseActionType(undefinedType: String)
case class UndefinedResponseActionTypeException(undefinedType: String)
extends Exception(s"Undefined response action content type: '$undefinedType'")

case class ContentValidationFailed(value: String, message: String)
case class ContentValidationFailedException(value: String, message: String)
extends Exception(s"Content validation failed for value: '$value': $message")

case class AssertionException(message: String)
extends Exception(s"Assertion failed: $message")
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package africa.absa.testing.scapi
import africa.absa.testing.scapi.config.ScAPIRunnerConfig
import africa.absa.testing.scapi.json.{Environment, EnvironmentFactory, SuiteFactory}
import africa.absa.testing.scapi.logging.Logger
import africa.absa.testing.scapi.model.{SuiteBundle, SuiteResults}
import africa.absa.testing.scapi.model.{SuiteBundle, SuiteResult}
import africa.absa.testing.scapi.reporter.StdOutReporter
import africa.absa.testing.scapi.rest.RestClient
import africa.absa.testing.scapi.rest.request.sender.ScAPIRequestSender
Expand Down Expand Up @@ -47,7 +47,7 @@ object ScAPIRunner {
Logger.setLevel(if (cmd.debug) Level.DEBUG else Level.INFO)
cmd.logConfigInfo()

if (!Files.exists(Paths.get(cmd.testRootPath, "suites"))) throw SuiteLoadFailed("'suites' directory have to exist in project root.")
if (!Files.exists(Paths.get(cmd.testRootPath, "suites"))) throw SuiteLoadFailedException("'suites' directory have to exist in project root.")

// jsons to objects
val environment: Environment = EnvironmentFactory.fromFile(cmd.envPath)
Expand All @@ -59,7 +59,7 @@ object ScAPIRunner {
Logger.info("Validate only => end run.")
} else {
Logger.info("Running tests")
val testResults: List[SuiteResults] = SuiteRunner.runSuites(suiteBundles, environment, () => new RestClient(ScAPIRequestSender))
val testResults: List[SuiteResult] = SuiteRunner.runSuites(suiteBundles, environment, () => new RestClient(ScAPIRequestSender))
StdOutReporter.printReport(testResults)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@

package africa.absa.testing.scapi.json

import africa.absa.testing.scapi.rest.response.ResponseActionGroupType.ResponseActionGroupType
import africa.absa.testing.scapi.utils.cache.RuntimeCache
import africa.absa.testing.scapi.{PropertyNotFound, UndefinedConstantsInProperties}
import africa.absa.testing.scapi.{PropertyNotFoundException, UndefinedConstantsInPropertiesException}

import scala.util.matching.Regex

Expand Down Expand Up @@ -56,10 +57,10 @@ sealed protected trait ReferenceResolver {
* If there are any unresolved references, it throws an exception.
*
* @param notResolvedReferences A set of unresolved reference keys.
* @throws UndefinedConstantsInProperties If there are any unresolved references.
* @throws UndefinedConstantsInPropertiesException If there are any unresolved references.
*/
private def notResolved(notResolvedReferences: Set[String]): Unit =
if (notResolvedReferences.nonEmpty) throw UndefinedConstantsInProperties(notResolvedReferences, s"'${getClass.getSimpleName}' action.")
if (notResolvedReferences.nonEmpty) throw UndefinedConstantsInPropertiesException(notResolvedReferences, s"'${getClass.getSimpleName}' action.")

/**
* Resolve a map of references to their actual values. It iteratively updates the map with resolved values.
Expand Down Expand Up @@ -114,7 +115,7 @@ case class Environment private(constants: Map[String, String], properties: Map[S
* @param key The key to retrieve the value for.
* @return The value corresponding to the key.
*/
def apply(key: String): String = properties.getOrElse(key, constants.getOrElse(key, throw PropertyNotFound(key)))
def apply(key: String): String = properties.getOrElse(key, constants.getOrElse(key, throw PropertyNotFoundException(key)))

/**
* Method to resolve all the references in the environment's properties.
Expand Down Expand Up @@ -207,14 +208,10 @@ case class Action private(methodName: String, url: String, body: Option[String]
* @param params the map containing the parameters of the response action. Each key-value pair in the map
* represents a parameter name and its corresponding value.
*/
case class ResponseAction private(method: String,
case class ResponseAction private(group: ResponseActionGroupType,
name: String,
params: Map[String, String]) extends ReferenceResolver {

private def splitter: Seq[String] = method.split("\\.").toSeq

def group : String = splitter.head
def name : String = splitter.tail.head

/**
* Method to resolve references.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import africa.absa.testing.scapi.json.schema.{JsonSchemaValidator, ScAPIJsonSche
import africa.absa.testing.scapi.logging.Logger
import africa.absa.testing.scapi.model._
import africa.absa.testing.scapi.rest.request.{RequestBody, RequestHeaders, RequestParams}
import africa.absa.testing.scapi.rest.response.Response
import africa.absa.testing.scapi.rest.response.{Response, ResponseActionGroupType}
import africa.absa.testing.scapi.utils.file.{FileUtils, JsonUtils}
import spray.json._

Expand Down Expand Up @@ -71,7 +71,7 @@ object SuiteFactory {
failedSuites.foreach { case (key, value) =>
Logger.error(s"$key => $value")
}
throw ProjectLoadFailed()
throw ProjectLoadFailedException()
}
}

Expand Down Expand Up @@ -324,16 +324,26 @@ object SuiteAfterJsonProtocol extends DefaultJsonProtocol {
object ResponseActionJsonProtocol extends DefaultJsonProtocol {

implicit object ResponseActionJsonFormat extends RootJsonFormat[ResponseAction] {
def write(a: ResponseAction): JsObject = JsObject(
("method" -> JsString(a.method)) +:
a.params.view.mapValues(JsString(_)).toSeq: _*
)
def write(a: ResponseAction): JsObject = {
val fixedFields = Seq(
"group" -> JsString(a.group.toString),
"name" -> JsString(a.name)
)

val paramFields = a.params.view.mapValues(JsString(_)).toSeq

JsObject((fixedFields ++ paramFields): _*)
}

def read(value: JsValue): ResponseAction = {
value.asJsObject.getFields("method") match {
case Seq(JsString(method)) =>
val splitter: Seq[String] = method.split("\\.").toSeq
val group = ResponseActionGroupType.fromString(splitter.head).getOrElse(
throw new IllegalArgumentException(s"Invalid action group: ${splitter.head}"))
val name = splitter.tail.head
val params = value.asJsObject.fields.view.toMap
ResponseAction(method, params.map { case (k, v) => k -> v.convertTo[String] })
ResponseAction(group, name, params.map { case (k, v) => k -> v.convertTo[String] })
case _ => throw DeserializationException("Assertion expected")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package africa.absa.testing.scapi.json.schema

import africa.absa.testing.scapi.JsonInvalidSchema
import africa.absa.testing.scapi.JsonInvalidSchemaException
import africa.absa.testing.scapi.utils.file.JsonUtils
import com.fasterxml.jackson.databind.{JsonNode, ObjectMapper}
import com.networknt.schema.{JsonSchema, JsonSchemaFactory, SpecVersion}
Expand Down Expand Up @@ -61,7 +61,7 @@ case class JsonSchemaValidator(jsonPath: String, schemaPath: URL) {
val errors = jsonSchema.validate(jsonNode)

import scala.jdk.CollectionConverters._
if (!errors.isEmpty) throw JsonInvalidSchema(jsonPath, errors.asScala)
if (!errors.isEmpty) throw JsonInvalidSchemaException(jsonPath, errors.asScala)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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 africa.absa.testing.scapi.model

import africa.absa.testing.scapi.model.SuiteResultType.SuiteResultType

import scala.util.{Failure, Try}

/**
* Case class representing the results of a suite test.
*
* @param resultType The type of the result (e.g. Before, Test, After)
* @param suiteName The name of the suite
* @param name The name of the test or method
* @param duration The duration of the test, if applicable
* @param categories The categories of the test, if any
* TODO
*/
case class SuiteResult(resultType: SuiteResultType,
suiteName: String,
name: String,
result: Try[Unit],
duration: Option[Long],
categories: Option[String] = None) {
/**
* Checks if the suite result was a success.
*
* @return true if the suite result was a success, false otherwise
*/
def isSuccess: Boolean = result.isSuccess

def errorMsg: Option[String] = result match {
case Failure(t) => Some(t.getMessage)
case _ => None
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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 africa.absa.testing.scapi.model

object SuiteResultType extends Enumeration {
val BEFORE_SUITE, TEST_SUITE, AFTER_SUITE = Value
type SuiteResultType = Value
}

This file was deleted.

Loading

0 comments on commit c203ab6

Please sign in to comment.