2022-05-31 15:36:54 +03:00
|
|
|
|
# Your First Hurl File
|
|
|
|
|
|
|
|
|
|
Throughout this tutorial, we'll walk through the creation of multiple
|
|
|
|
|
Hurl files to test a basic quiz application. We'll show how to test
|
|
|
|
|
this site locally, and how to automate these integration tests in a CI/CD
|
|
|
|
|
chain like [GitHub Action] and [GitLab CI/CD].
|
|
|
|
|
|
|
|
|
|
The quiz application consists of:
|
|
|
|
|
|
|
|
|
|
- a website that lets people create or play a series of quizzes
|
|
|
|
|
- a set of REST apis to list, create and delete question and quiz
|
|
|
|
|
|
|
|
|
|
With Hurl, we're going to add tests for the website and the apis.
|
|
|
|
|
|
|
|
|
|
## Prerequisites
|
|
|
|
|
|
|
|
|
|
We’ll assume you have Hurl installed already. You can test it by running the
|
|
|
|
|
following command in a shell prompt (indicated by the $ prefix):
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
$ hurl --version
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If Hurl is already installed, you should see the version of Hurl. If it isn't, you
|
|
|
|
|
can check [Installation] to see how to install Hurl.
|
|
|
|
|
|
|
|
|
|
Next, we’re going to install our quiz application locally, in order to test it. We are
|
|
|
|
|
not going to build our application from scratch, in order to focus on how to test it.
|
|
|
|
|
|
|
|
|
|
> Hurl being really language agnostic, you can use it to validate any type of application: in
|
|
|
|
|
> this tutorial, our quiz application is built with [Spring Boot],
|
|
|
|
|
> but this could as well be a [Node.js] or a [Flask] app.
|
|
|
|
|
|
|
|
|
|
Our quiz application can be launched locally either:
|
|
|
|
|
|
|
|
|
|
- using a Docker image
|
|
|
|
|
- directly using the jar of the application
|
|
|
|
|
|
|
|
|
|
If you want to use the Docker image, you must have Docker installed locally. If it is the case,
|
|
|
|
|
just run in a shell:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
$ docker pull ghcr.io/jcamiel/quiz:latest
|
|
|
|
|
$ docker run --name quiz --rm --detach --publish 8080:8080 ghcr.io/jcamiel/quiz:latest
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
And check that the container is running with:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
$ docker ps
|
|
|
|
|
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
|
|
|
|
922d387923ec ghcr.io/jcamiel/quiz:latest "java -jar app/quiz.…" 8 seconds ago Up 6 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp quiz
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If you want to use the jar application, you must have Java installed locally. If it is the case, download
|
|
|
|
|
the jar application from <https://github.com/jcamiel/quiz/releases/latest> and run in a shell:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
$ java -jar quiz-0.0.2.jar
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Either you're using the Docker images ot the jar app, you can open a browser and test the quiz application by
|
|
|
|
|
typing the url <http://localhost:8080>:
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<img class="light-img" src="/docs/assets/img/quiz-light.png" width="400px" alt="Quiz home page"/>
|
|
|
|
|
<img class="dark-img" src="/docs/assets/img/quiz-dark.png" width="400px" alt="Quiz home page"/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<small>Our quiz app: we've only secured a budget for integration tests and nothing for the site design...</small>
|
|
|
|
|
|
|
|
|
|
## A Basic Test
|
|
|
|
|
|
|
|
|
|
Next, we’re going to write our first test.
|
|
|
|
|
|
2022-06-11 13:49:24 +03:00
|
|
|
|
1. Open a text editor and create a file named `basic.hurl`. In this file, just type the following text and save:
|
2022-05-31 15:36:54 +03:00
|
|
|
|
|
|
|
|
|
```hurl
|
|
|
|
|
GET http://localhost:8080
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This is your first Hurl file, and probably one of the simplest. It consists of only one [entry].
|
|
|
|
|
|
|
|
|
|
> An entry has a mandatory [request specification]: in this case, we want to perform a
|
|
|
|
|
> `GET` HTTP request on the endpoint <http://localhost:8080>. A request can be optionally followed by a [response
|
|
|
|
|
> description], to add asserts on the HTTP response. For the moment, we don't have any response description.
|
|
|
|
|
|
2022-06-11 13:49:24 +03:00
|
|
|
|
2. In a shell, execute `hurl` with `basic.hurl` as argument:
|
2022-05-31 15:36:54 +03:00
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
$ hurl basic.hurl
|
|
|
|
|
<!doctype html>
|
|
|
|
|
<html lang="en">
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="utf-8">
|
|
|
|
|
<title>Welcome to Quiz!</title>
|
|
|
|
|
<!-- <link rel="stylesheet" href="style.css">
|
|
|
|
|
<script src="script.js"></script>-->
|
|
|
|
|
</head>
|
|
|
|
|
....
|
|
|
|
|
</html>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If the quiz app is running, you should see the content of the html file at <http://localhost:8080>. If the quiz app
|
|
|
|
|
is not running, you'll see an error:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
$ hurl basic.hurl
|
2022-08-16 16:30:48 +03:00
|
|
|
|
[1;31merror[0m: [1mHTTP connection[0m
|
|
|
|
|
[1;34m-->[0m basic.hurl:1:5
|
|
|
|
|
[1;34m|[0m
|
|
|
|
|
[1;34m 1[0m [1;34m|[0m GET http://localhost:8080
|
|
|
|
|
[1;34m|[0m [1;31m^^^^^^^^^^^^^^^^^^^^^[0m [1;31m(7) Failed to connect to localhost port 8080: Connection refused[0m
|
|
|
|
|
[1;34m|[0m
|
2022-05-31 15:36:54 +03:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
As there are no response description, this basic test only checks that an HTTP server is running at
|
|
|
|
|
<http://localhost:8080> and responds _something_. If the server had a problem on this endpoint, and had responded
|
|
|
|
|
with a [`500 Internal Server Error`], Hurl would have just executed successfully the HTTP request,
|
|
|
|
|
without checking the actual HTTP response.
|
|
|
|
|
|
|
|
|
|
As this test is not sufficient to ensure that our server is alive and running, we're going to add some asserts on
|
|
|
|
|
the response and, at least, check that the HTTP response status code is [`200 OK`].
|
|
|
|
|
|
2022-06-11 13:49:24 +03:00
|
|
|
|
3. Open `basic.hurl` and modify it to test the status code response:
|
2022-05-31 15:36:54 +03:00
|
|
|
|
|
|
|
|
|
```hurl
|
|
|
|
|
GET http://localhost:8080
|
|
|
|
|
HTTP/1.1 200
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
4. Execute `basic.hurl`:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
$ hurl basic.hurl
|
|
|
|
|
<!doctype html>
|
|
|
|
|
<html lang="en">
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="utf-8">
|
|
|
|
|
<title>Welcome to Quiz!</title>
|
|
|
|
|
<link rel="stylesheet" href="style.css">
|
|
|
|
|
<script src="script.js"></script>
|
|
|
|
|
</head>
|
|
|
|
|
....
|
|
|
|
|
</html>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
There is no modification to the output of Hurl, the content of the HTTP request is outputted to the terminal. But, now,
|
2022-06-11 13:49:24 +03:00
|
|
|
|
we check that our server is responding with a `200 OK`.
|
2022-05-31 15:36:54 +03:00
|
|
|
|
|
2022-06-11 13:49:24 +03:00
|
|
|
|
By default, Hurl behaves like [curl] and outputs the HTTP response. This is useful when you want to get data from a
|
|
|
|
|
server, and you need to perform additional steps (like login, confirmation etc...) before being able to call your last
|
|
|
|
|
request.
|
|
|
|
|
|
|
|
|
|
In our case, we want to add tests to our project, so we can use [`--test`] command line option to have an adapted
|
|
|
|
|
test output:
|
|
|
|
|
|
|
|
|
|
5. Execute `basic.hurl` in test mode:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
$ hurl --test basic.hurl
|
2022-08-16 16:30:48 +03:00
|
|
|
|
[1mbasic.hurl[0m: [1;36mRunning[0m [1/1]
|
|
|
|
|
[1mbasic.hurl[0m: [1;32mSuccess[0m
|
2022-06-11 13:49:24 +03:00
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
Executed: 1
|
|
|
|
|
Succeeded: 1 (100.0%)
|
|
|
|
|
Failed: 0 (0.0%)
|
2022-08-16 16:30:48 +03:00
|
|
|
|
Duration: 7ms
|
2022-06-11 13:49:24 +03:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
6. Modify `basic.hurl` to test a different HTTP response status code:
|
2022-05-31 15:36:54 +03:00
|
|
|
|
|
|
|
|
|
```hurl
|
|
|
|
|
GET http://localhost:8080
|
|
|
|
|
HTTP/1.1 500
|
|
|
|
|
```
|
|
|
|
|
|
2022-06-11 13:49:24 +03:00
|
|
|
|
7. Save and execute it:
|
2022-05-31 15:36:54 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
2022-06-11 13:49:24 +03:00
|
|
|
|
$ hurl --test basic.hurl
|
2022-08-16 16:30:48 +03:00
|
|
|
|
[1mbasic.hurl[0m: [1;36mRunning[0m [1/1]
|
|
|
|
|
[1;31merror[0m: [1mAssert status code[0m
|
|
|
|
|
[1;34m-->[0m basic.hurl:2:10
|
|
|
|
|
[1;34m|[0m
|
|
|
|
|
[1;34m 2[0m [1;34m|[0m HTTP/1.1 500
|
|
|
|
|
[1;34m|[0m [1;31m^^^[0m [1;31mactual value is <200>[0m
|
|
|
|
|
[1;34m|[0m
|
|
|
|
|
|
|
|
|
|
[1mbasic.hurl[0m: [1;31mFailure[0m
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
Executed: 1
|
|
|
|
|
Succeeded: 0 (0.0%)
|
|
|
|
|
Failed: 1 (100.0%)
|
|
|
|
|
Duration: 5ms
|
2022-05-31 15:36:54 +03:00
|
|
|
|
```
|
|
|
|
|
|
2022-06-11 13:49:24 +03:00
|
|
|
|
8. Revert your changes and finally add a comment at the beginning of the file:
|
2022-05-31 15:36:54 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```hurl
|
|
|
|
|
# Our first Hurl file, just checking
|
|
|
|
|
# that our server is up and running.
|
|
|
|
|
GET http://localhost:8080
|
|
|
|
|
HTTP/1.1 200
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Recap
|
|
|
|
|
|
|
|
|
|
That's it, this is your first Hurl file!
|
|
|
|
|
|
|
|
|
|
This is really a basic test, but Hurl's file format strength is its simplicity.
|
|
|
|
|
We're going to see in the next section how to improve our tests while keeping it really simple.
|
|
|
|
|
|
|
|
|
|
[GitHub Action]: https://github.com/features/actions
|
|
|
|
|
[GitLab CI/CD]: https://docs.gitlab.com/ee/ci/
|
|
|
|
|
[Installation]: /docs/installation.md
|
|
|
|
|
[Spring Boot]: https://spring.io/projects/spring-boot
|
|
|
|
|
[Node.js]: https://nodejs.org/en/
|
|
|
|
|
[Flask]: https://flask.palletsprojects.com
|
|
|
|
|
[entry]: /docs/entry.md
|
|
|
|
|
[request specification]: /docs/request.md
|
|
|
|
|
[response description]: /docs/response.md
|
|
|
|
|
[`500 Internal Server Error`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500
|
|
|
|
|
[`200 OK`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200
|
2022-06-11 13:49:24 +03:00
|
|
|
|
[`--test`]: /docs/man-page.md#test
|
|
|
|
|
[curl]: https://curl.se
|