-
Notifications
You must be signed in to change notification settings - Fork 0
Checks API
OBSOLETE!!! TO BE REWRITTEN FOR 1.1.0
The Check API was created to allow easy addition of new checks to Gatling. All the built-in checks were created on top of this API. For a better understanding of Checks, we encourage you to read the Check Reference.
Checks are like information containers: they are made to be used by a request protocol. The life cycle of a check is managed by the protocol plugin/module that uses it.
To create a check plugin, there are at least 4 components to create:
- A Check
- A Check Builder
- An Extractor
- An Extractor Factory
The Check Builder is the class that will be used in Gatling's DSL to use the check. It basically adds one or more methods allowing users to declare the check (eg: the header(headerName: String)
method).
The Extractor is the component responsible for the extraction of the value(s) to be checked in the response of the server. For example, the HttpHeaderExtractor
allows the extraction of the headers in an HTTP response.
This component is used to get an Extractor when applying a check. It was created to be able to get either a multi-valued extractor or a single-valued extractor.
As said above, the Check is a container for all the information needed to run this check, it will contain:
- The used Extractor Factory
- The expression for the extraction of the values in the response (eg: an XPath expression if you want to create an XPath check)
- The strategy used to verify the information (corresponds to
eq
,neq
, etc.) - The expected value of what was extracted (if required)
- The session attribute under which the extracted value should be saved
To help you understand the Check API, we will suppose that the Header checks do not exist yet, and we will create it from the ground up.
The first thing to do is to verify if we already have an HTTP Header Extractor. This is where everything starts: getting the header to check it.
To do so, we create an Extractor:
class HttpHeaderExtractor(response: Response) extends Extractor {
def extract(headerName: String): List[String] = {
response.getHeaders.get(headerName) match {
case null => Nil
case l => l.toList
}
}
}
This extractor takes an HttpResponse
as attribute as we want to extract the headers from the response. The extract method takes the expression (as a String) that identifies the element that should be extracted, in our case: the header name.
Depending on whether the header has been found or not we return Nil or a list containing the value of the header.
Note: We tried hard to have single valued extractors return a String, but it would make the API much more complicated than it is now.
To get the extractor we will need an Extractor Factory:
object HttpHeaderExtractorFactory extends ExtractorFactory[Response] {
def getExtractor(response: Response) = new HttpHeaderExtractor(response)
}
The generic type of ExtractorFactory[T]
allows you to define from where the extraction should be made. It also determines the type of the argument that should be passed to the getExtractor
method.
We have defined the extractor needed to get the headers from the response, now we can create the Check that will use it:
class HttpHeaderCheck(what: Session => String, strategy: (List[String], List[String]) => Boolean, expected: List[Session => String], saveAs: Option[String])
extends HttpCheck(what, HttpHeaderExtractorFactory, strategy, expected, saveAs, CompletePageReceived)
As you can see, here our check extends HttpCheck
which extends Check
. The inheritance is used to add an additionnal information to the Check: the phase on which it should be processed. In our example, the check should be executed when the response has been completely received so we can use the Response
object.
Finally, you can see that we used ou HttpHeaderExtractorFactory
in the declaration of our class.
Now that we have our check, it can be used by Gatling. The last step is to provide users with a way to declare it. To add a method in the DSL we use Check Builders:
object HttpHeaderCheckBuilder {
def header(what: Session => String) = new HttpHeaderCheckBuilder(what, CheckBuilderVerify.exists, Nil, None) with CheckBuilderFind[HttpCheckBuilder[HttpHeaderCheckBuilder]]
def header(headerName: String): HttpHeaderCheckBuilder with CheckBuilderFind[HttpCheckBuilder[HttpHeaderCheckBuilder]] = header(interpolate(headerName))
}
class HttpHeaderCheckBuilder(what: Session => String, strategy: (List[String], List[String]) => Boolean, expected: List[Session => String], saveAs: Option[String])
extends HttpCheckBuilder[HttpHeaderCheckBuilder](what, None, strategy, expected, saveAs, HeadersReceived) {
private[http] def newInstance(what: Session => String, occurrence: Option[Int], strategy: (List[String], List[String]) => Boolean, expected: List[Session => String], saveAs: Option[String], when: HttpPhase) =
new HttpHeaderCheckBuilder(what, strategy, expected, saveAs)
private[gatling] def newInstanceWithFindOne(occurrence: Int) =
new HttpHeaderCheckBuilder(what, strategy, expected, saveAs) with CheckBuilderVerifyOne[HttpCheckBuilder[HttpHeaderCheckBuilder]]
private[gatling] def newInstanceWithFindAll = throw new UnsupportedOperationException("Header checks are single valued")
private[gatling] def newInstanceWithVerify(strategy: (List[String], List[String]) => Boolean, expected: List[Session => String] = Nil) =
new HttpHeaderCheckBuilder(what, strategy, expected, saveAs) with CheckBuilderSave[HttpCheckBuilder[HttpHeaderCheckBuilder]]
private[gatling] def build: HttpCheck = new HttpHeaderCheck(what, strategy, expected, saveAs)
}
This is the most complicated class to create at first sight. As a matter of fact, there are several new concepts in this piece of code.
The DSL for checks, explained here, is ordered: check.find.verify.saveAs
. If you specify a verification method (or check strategy: eq
, neq
, etc.), you cannot specify the valuation of the check, it will be single-valued.
To achieve this goal, we used traits to force the order:
Schema with the hierarchy of the checkbuilderXXX
- Introduction
- Underlying Technologies
- Concepts
- Sponsors
- Changelog
- Migrating
- Continuous Integration
- Benchmarks
- License
- FAQ
- Contributing
- Events
- Links
- Tutorial
- Reference
- Cookbooks
- Extensions
- General information
- APIs
- Checks API
- Request API
- Charting API
- Feeder API