101 lines
3.3 KiB
Markdown
101 lines
3.3 KiB
Markdown
|
+++
|
||
|
title = "Refactored Tests and Pre-Commits"
|
||
|
date = 2023-03-20T17:38:12Z
|
||
|
weight = 3
|
||
|
+++
|
||
|
|
||
|
## Chapter 3.7 (Sort-of): A brief diversion
|
||
|
|
||
|
Re-reading the text, I made a number of changes. The first is that, while it is
|
||
|
nice that Rust allows us to have unit tests in the file whose functionality
|
||
|
we're testing, it's also nice to have the tests somewhere separate, and to have
|
||
|
the tests be a little more modular.
|
||
|
|
||
|
In the `./tests` folder, you can now see the same `health_check` test as the
|
||
|
original, but in an isolated and cleaned-up form. Most importantly, the server
|
||
|
startup code is now in its own function, with a correct return type that
|
||
|
includes a handle to the spawned thread and the address on which that server is
|
||
|
listening; tests can be run in parallel on many different ports and a lot of
|
||
|
code duplication is eliminated.
|
||
|
|
||
|
``` rust
|
||
|
type NullHandle = JoinHandle<()>;
|
||
|
|
||
|
async fn spawn_server() -> (SocketAddr, NullHandle) {
|
||
|
let listener = TcpListener::bind("127.0.0.1:0".parse::<SocketAddr>().unwrap()).unwrap();
|
||
|
let addr = listener.local_addr().unwrap();
|
||
|
|
||
|
let handle: NullHandle = tokio::spawn(async move {
|
||
|
axum::Server::from_tcp(listener)
|
||
|
.unwrap()
|
||
|
.serve(app().into_make_service())
|
||
|
.await
|
||
|
.unwrap();
|
||
|
});
|
||
|
|
||
|
(addr, handle)
|
||
|
}
|
||
|
```
|
||
|
|
||
|
It is also possible now to add new tests in a straightforward manner. The
|
||
|
Hyper API is not that much different from the Actix request API, and the Axum
|
||
|
extractors seem to be straightforward. I suspect that what I'm looking at here
|
||
|
with the handle is the idea that, when it goes out of scope, it calls a d
|
||
|
|
||
|
## Adding some checks
|
||
|
|
||
|
In the introduction I said I was going to be neglecting CI/CD, since I'm a solo
|
||
|
developer. That's true, but I do like my guardrails. I like not being able to
|
||
|
commit garbage to the repository. So I'm going to add some checks, using
|
||
|
[Pre-Commit](https://pre-commit.com/).
|
||
|
|
||
|
Pre-Commit is a Python program, so we'll start by installing it. I'm using a
|
||
|
local Python environment kickstarted with
|
||
|
[Pyenv](https://github.com/pyenv/pyenv).
|
||
|
|
||
|
``` sh
|
||
|
$ pip install pre-commit
|
||
|
```
|
||
|
|
||
|
And inside your project, in the project root, you hook it up with the following commands:
|
||
|
|
||
|
``` sh
|
||
|
$ pre-commit install
|
||
|
$ pre-commit sample-config > .pre-commit-config.yaml
|
||
|
```
|
||
|
|
||
|
I'm going with the default from the rust pre-commit collection, so my
|
||
|
`.pre-commit-config.yaml` file looks like this:
|
||
|
|
||
|
``` yaml
|
||
|
repos:
|
||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||
|
rev: v3.1.0
|
||
|
hooks:
|
||
|
- id: check-byte-order-marker
|
||
|
- id: check-case-conflict
|
||
|
- id: check-merge-conflict
|
||
|
- id: check-symlinks
|
||
|
- id: check-yaml
|
||
|
- id: end-of-file-fixer
|
||
|
- id: mixed-line-ending
|
||
|
- id: trailing-whitespace
|
||
|
- repo: https://github.com/pre-commit/pre-commit
|
||
|
rev: v2.5.1
|
||
|
hooks:
|
||
|
- id: validate_manifest
|
||
|
- repo: https://github.com/doublify/pre-commit-rust
|
||
|
rev: master
|
||
|
hooks:
|
||
|
- id: fmt
|
||
|
- id: cargo-check
|
||
|
- id: clippy
|
||
|
```
|
||
|
|
||
|
... and with that, every time I try to commit my code, it will not let me until
|
||
|
these tests pass. And I *like* that level of discipline. This is low-level
|
||
|
validation; it won't catch if I put addition where I meant subtraction, or if I
|
||
|
have a comparison going in the wrong direction, but at least the basics are
|
||
|
handled and, more importantly, the formatting and styling is consistent
|
||
|
throughout all of my code.
|