2022-05-31 15:36:54 +03:00
# Your First Hurl File
Throughout this tutorial, we'll walk through the creation of multiple
2023-07-21 14:28:26 +03:00
Hurl files to test a basic web application about movies called _Movies Box_ . We'll show how to test
2022-05-31 15:36:54 +03:00
this site locally, and how to automate these integration tests in a CI/CD
chain like [GitHub Action] and [GitLab CI/CD].
2023-07-21 14:28:26 +03:00
Our Movies Box website consists of:
2022-05-31 15:36:54 +03:00
2023-07-21 14:28:26 +03:00
- a website that lets people make list of favorite movies
- a set of REST APIs to search movies, add, remove favorites
2022-05-31 15:36:54 +03:00
2022-09-28 11:34:00 +03:00
With Hurl, we're going to add tests for the website and the APIs.
2022-05-31 15:36:54 +03:00
## 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.
2023-07-21 14:28:26 +03:00
Next, we’ re going to install our movies application locally, in order to test it.
2022-05-31 15:36:54 +03:00
> Hurl being really language agnostic, you can use it to validate any type of application: in
2023-07-21 14:28:26 +03:00
> this tutorial, our quiz application is built with [Express], a [Node.js] framework,
> but this could as well be a [Spring Boot] or a [Flask] app.
2022-05-31 15:36:54 +03:00
2023-07-21 14:28:26 +03:00
Our movies application can be launched locally either:
2022-05-31 15:36:54 +03:00
- using a Docker image
2023-07-21 14:28:26 +03:00
- using Node
2022-05-31 15:36:54 +03:00
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
2023-07-21 14:28:26 +03:00
$ docker pull ghcr.io/jcamiel/hurl-express-tutorial:latest
$ docker run --name movies --rm --detach --publish 3000:3000 ghcr.io/jcamiel/hurl-express-tutorial:latest
2022-05-31 15:36:54 +03:00
```
And check that the container is running with:
```shell
$ docker ps
2023-07-21 14:28:26 +03:00
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4002ce42e507 ghcr.io/jcamiel/hurl-express-tutorial:latest "node dist/bin/www.js" 3 seconds ago Up 2 seconds 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp movies
2022-05-31 15:36:54 +03:00
```
2023-07-21 14:28:26 +03:00
If you want to launch the Node application, you must have Node installed locally.
2022-05-31 15:36:54 +03:00
```shell
2023-07-21 14:28:26 +03:00
$ git clone https://github.com/jcamiel/hurl-express-tutorial.git & & cd hurl-express-tutorial
$ npm install
$ npm start
2022-05-31 15:36:54 +03:00
```
2023-07-21 14:28:26 +03:00
Either you're using the Docker images or the Node app, you can open a browser and test the website by
typing the URL < http: / / localhost:3000 > :
< div class = "picture" >
< picture >
< source srcset = "/docs/assets/img/movies-box-light.avif" type = "image/avif" >
< source srcset = "/docs/assets/img/movies-box-light.webp" type = "image/webp" >
< source srcset = "/docs/assets/img/movies-box-light.png" type = "image/png" >
< img class = "light-img u-drop-shadow u-border u-max-width-100" src = "/docs/assets/img/movies-box-light.png" width = "600" alt = "Movies Box home page" / >
< / picture >
< picture >
< source srcset = "/docs/assets/img/movies-box-dark.avif" type = "image/avif" >
< source srcset = "/docs/assets/img/movies-box-dark.webp" type = "image/webp" >
< source srcset = "/docs/assets/img/movies-box-dark.png" type = "image/png" >
< img class = "dark-img u-drop-shadow u-border u-max-width-100" src = "/docs/assets/img/movies-box-dark.png" width = "600" alt = "Movies Box home page" / >
< / picture >
2022-05-31 15:36:54 +03:00
< / div >
2023-07-21 14:28:26 +03:00
Play a little with the site. You can see details of each movie, search for movies (try "1982"), login to add favorites
(use username `fab` and password `12345678` ).
2022-05-31 15:36:54 +03:00
## 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
2023-07-21 14:28:26 +03:00
GET http://localhost:3000
2022-05-31 15:36:54 +03:00
```
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
2023-07-21 14:28:26 +03:00
> `GET` HTTP request on the endpoint <http://localhost:3000>. A request can be optionally followed by a [response
2022-05-31 15:36:54 +03:00
> 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" >
2023-07-21 14:28:26 +03:00
< head >
< meta charset = "UTF-8" / >
< title > Movies Box< / title >
< link rel = "icon" type = "image/png" href = "/img/favicon.png" / >
< link rel = "stylesheet" href = "/css/style.css" / >
< / head >
< body >
2022-05-31 15:36:54 +03:00
....
< / html >
```
2023-07-21 14:28:26 +03:00
If the Movies Box website is running, you should see the content of the HTML file at < http: / / localhost:3000 > .
If the website is not running, you'll see an error:
2022-05-31 15:36:54 +03:00
```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
2023-07-21 14:28:26 +03:00
[1;34m 1 [0m [1;34m| [0m GET http://localhost:3000
[1;34m| [0m [1;31m^^^^^^^^^^^^^^^^^^^^^ [0m [1;31m(7) Failed to connect to localhost port 3000 after 6 ms: Couldn't connect to server [0m
2022-08-16 16:30:48 +03:00
[1;34m| [0m
2022-05-31 15:36:54 +03:00
```
2022-09-28 11:24:24 +03:00
As there is no response description, this basic test only checks that an HTTP server is running at
2023-07-21 14:28:26 +03:00
< http: // localhost:3000 > and responds with _something_ . If the server had a problem on this endpoint, and had responded
2022-05-31 15:36:54 +03:00
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
2023-07-21 14:28:26 +03:00
GET http://localhost:3000
2022-12-19 23:30:08 +03:00
HTTP 200
2022-05-31 15:36:54 +03:00
```
4. Execute `basic.hurl` :
```shell
$ hurl basic.hurl
<!doctype html>
< html lang = "en" >
2023-07-21 14:28:26 +03:00
< head >
< meta charset = "UTF-8" / >
< title > Movies Box< / title >
< link rel = "icon" type = "image/png" href = "/img/favicon.png" / >
< link rel = "stylesheet" href = "/css/style.css" / >
< / head >
< body >
2022-05-31 15:36:54 +03:00
....
< / 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]
2023-07-21 14:28:26 +03:00
[1mbasic.hurl [0m: [1;32mSuccess [0m (1 request(s) in 25 ms)
2022-06-11 13:49:24 +03:00
--------------------------------------------------------------------------------
2022-08-23 19:36:47 +03:00
Executed files: 1
Succeeded files: 1 (100.0%)
Failed files: 0 (0.0%)
2023-07-21 14:28:26 +03:00
Duration: 27 ms
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
2023-07-21 14:28:26 +03:00
GET http://localhost:3000
2022-12-19 23:30:08 +03:00
HTTP 500
2022-05-31 15:36:54 +03:00
```
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
2023-07-21 14:28:26 +03:00
[1;34m--> [0m basic.hurl:2:6
2022-08-16 16:30:48 +03:00
[1;34m| [0m
2023-07-21 14:28:26 +03:00
[1;34m 2 [0m [1;34m| [0m HTTP 500
[1;34m| [0m [1;31m^^^ [0m [1;31mactual value is < 200 > [0m
2022-08-16 16:30:48 +03:00
[1;34m| [0m
2023-07-21 14:28:26 +03:00
[1mbasic.hurl [0m: [1;31mFailure [0m (1 request(s) in 20 ms)
2022-08-16 16:30:48 +03:00
--------------------------------------------------------------------------------
2022-08-23 19:36:47 +03:00
Executed files: 1
Succeeded files: 0 (0.0%)
Failed files: 1 (100.0%)
2023-07-21 14:28:26 +03:00
Duration: 21 ms
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.
2023-08-18 13:39:27 +03:00
GET http://localhost:3000
2022-12-19 23:30:08 +03:00
HTTP 200
2022-05-31 15:36:54 +03:00
```
## Recap
That's it, this is your first Hurl file!
2022-09-28 11:24:24 +03:00
This is really a basic test, but it shows how powerful Hurl's simple file format is.
2022-05-31 15:36:54 +03:00
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-09-02 15:45:54 +03:00
[`--test`]: /docs/manual.md#test
2022-09-28 11:34:00 +03:00
[curl]: https://curl.se
2023-07-21 14:28:26 +03:00
[Express]: https://expressjs.com