Introduction

Rust is a powerful language built on the promise of performance and reliability. With no runtime or garbage collector, it easily runs in any environment and can be integrated into any existing language or framework. With the advent of WebAssembly. Rust has become even more valued in the web development space. Rust’s seamless peering with Node.js to build highly performant functionalities has made it a delight for web developers. Many web developers would rather write Rust than have to learn/write C++ or C for WebAssembly integrations.

In this tutorial, you will learn and demonstrate how to automatically test Rust applications as you push updates and upgrades in your Rust applications to a remote repository.

Prerequisites

To follow along with the tutorial, a few things are required:

  1. Basic knowledge of Rust
  2. Rust installed on your system (find installation instructions here)
  3. A CircleCI account
  4. A GitHub account

With all these installed and set up, it is time to begin the tutorial.

Creating a new Rust project

If you have already installed Rust before starting this project, make sure you run rustup update so your current installation is compatible. To begin, create a new Rust application by running this command:

cargo new rust-testing

This command quickly scaffolds a barebones Rust application inside the rust-testing folder. You will build a simple CLI application that prompts the user for a name and prints a greeting message back to the CLI.

Locate the file src/main.rs and replace its content with this code:

fn main() {
    let mut line = String::new();
    println!("Please enter your name: ");
    std::io::stdin().read_line(&mut line).unwrap();
    println!("{}", build_message(line));
}

fn build_message(name: String) -> String{
    let message = "You are welcome ".to_owned() + &name;
    return message;
}

In the code above, a build_message function is defined which takes in a name argument of type String and returns a greeting message constructed using the name argument.

The main function prompts the user for a name. The name is then passed to the build_message function and its return value printed out to the CLI output.

Run this program by running the command below at the root of the project folder.

cargo run

The application will prompt you for your name. Enter your name and hit the Enter key to see the greeting message printed to the CLI screen as shown below.

Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/rust-testing`
Please enter your name: 
Fikayo Adepoju
You are welcome Fikayo Adepoju

Adding tests for the Rust application

One of the beauties of Rust is that it comes bundled with its own testing framework, and requires no additional setup. You will be writing a unit test for the build_message function to assert its output. Unlike most other languages and frameworks that place tests in separate files, Rust actually encourages you to place your unit tests in the same file as the piece of code being tested.

The cargo test command for running tests in a Rust application will locate any function with the #[test] attribute in the project and run it as a test case.

Add this test case just below the build_message function:

#[test]
fn test_build_message(){
    let name = String::from("Fikayo");

    assert_eq!(build_message(name), "You are welcome Fikayo")
}

In this test, a name variable is declared and assigned a String value of Fikayo. The next line then checks that the build_message function returns the expected message for the argument passed in.

To run this test, run:

cargo test

The test should run successfully. This is the output that will appear on your CLI:

Compiling rust-testing v0.1.0 (/Users/stanmd/Projects/CCI/rust-testing)
    Finished test [unoptimized + debuginfo] target(s) in 0.63s
     Running target/debug/deps/rust_testing-5cffbb684dbc6899

running 1 test
test test_build_message ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Connecting the Rust application to CircleCI

To begin the test automation process for your Rust project, you need to push the project to GitHub.

Next, go to the Projects page on the CircleCI dashboard. Select the appropriate GitHub account and add the project.

Add Project - CircleCI

Click Set Up Project.

Add Config - CircleCI

On the setup page, click Use Existing Config to indicate that you are setting up a configuration file manually and not using the sample displayed. Next, you get a prompt to either download a configuration file for the pipeline or to start building.

Build Prompt - CircleCI

Click Start Building. This build will fail because you have not set up your configuration file yet. We will build this file in the next step.

Automating tests for the Rust application

Time to write the continuous integration script that will automate the running of tests in the project any time updates are pushed to the remote code repository.

At the root of your project, create a folder named .circleci and add a file named config.yml to it. Inside config.yml, enter this code:

version: 2.1

jobs:
  build:
    docker:
      - image: cimg/rust:1.50.0
    steps:
      - checkout
      - run: cargo --version
      - run:
          name: Run Tests
          command: "cargo test"

This code pulls in the CircleCI Rust image cimg/rust:1.50.0. This image gives you access to all CLI commands available for a Rust installation.

The code is then pulled from the remote repository and the step labelled Run Tests uses the cargo test command to run tests contained in the project.

Commit all changes to the project and push to your remote GitHub repository. The integration pipeline is triggered, and you should have a successful build.

Build Successful - CircleCI

Click the build job for details about the deployment.

Build Details - CircleCI

Now, each time you change your code, either by adding more features or more tests, and then push to your remote repository, your tests will automatically run. You will be alerted if your build failed due to a broken piece of code.

Smooth!

Conclusion

In this tutorial, you have learned and demonstrated how to automate tests in your Rust projects using a continuous integration pipeline. To expand your knowledge, learn how to continously deploy Rust applications. From start to finish, you can increase the value of Rust for your team so you can build better apps, faster.

Happy coding!


Fikayo Adepoju is a Full-stack developer, technical writer, and tech content creator proficient in Web and Mobile technologies and DevOps with over 10 years experience developing scalable distributed applications. With over 40 articles written for CircleCI, Twilio, Auth0, and The New Stack blogs and also on his personal Medium page, he loves to share his knowledge to as many developers as would benefit from it. You can also check out his video courses on Udemy.