How do I pass configuration like server addresses to Rust tests? - rust

I want to code a crate for a REST API. cargo test needs a server where the features can be tested, so I need something like adding "parameters" to the tests.
I looked at the documentation of cargo test to see if I can add command line options like cargo test -- --api-server=https://localhost:80 but it doesn't seem to exist.

Related

Grouping tests in Rust/Cargo

I really love cargo and how easy it is to write unit tests.
However, it seems like it's testing functionality is fairly basic. What I'd like to be able to do is have named groups of tests somehow. What I am trying to accomplish is to have a default set of tests that execute when you run the basic cargo test. However, some of my tests take much longer to run, so I'd like to be able to move these to another group of extended tests that I can run with some command like cargo test --extended, and also the ability to be able to run all the tests at once easily. I also have a third group of tests that I have currently implemented as ignored tests so I can run them separately.
Even though all my tests are effectively unit tests, I tried to accomplish this by creating a tests directory as you would do with integration tests. However it seems that the basic cargo test command wants to run the all these tests, i.e. the normal tests that are part of my crate as well as the extended tests in the tests crate.
Does anyone know how to accomplish this or whether there is some crate that provides this functionality?
You could use a combination of feature flags and the #ignore macro as mentioned here: https://www.reddit.com/r/rust/comments/3i1nki/how_to_skip_expensive_tests_with_cargo_test/

Can we download something & set environment variable during crate installation?

As a Rust driver crate developer, I would like to perform below steps during my crate installation/download when used by any other Rust program:
Check the platform i.e. Windows or UNIX or macOS.
Download the corresponding platform-specific binary from an external website.
Set an environment variable pointing to the download location.
I know this is possible in Node or Python or R but not sure if this is possible in Rust.
You can use Build script to achieve that (but it is not what you should do, please see note below).
The script will be compiled and executed before cargo start building your library.
Inside the script you can use cfg attribute to check platform.
There is a bunch of libraries to download something via HTTP, for example reqwest
You can set environment variable via cargo:rustc-env=VAR=VALUE
IMPORTANT NOTE
Most of Rust users doesn't expect that kind of behavior from build script. There may be dozen of problems with the approach. Just few of them from the top of my head:
First of all there may be security issues.
The approach will break builds at client side.
I believe it's better to upload all binaries you need as a part of the crate. You can use include_bytes! for that.

How to handle 3rd-party static C library dependencies in Rust/Cargo?

There is a 3rd party C library that I'd like to link to in my Rust project. It is hosted on github and compiles only as a static library. Is there any way to have Cargo fetch this dependency for me? I'm thinking there isn't. I tried adding it as a dependency and got a "Could not find Cargo.toml in ..." error.
As an alternative, I thought of modifying my build.rs file to use the git2-rs crate to download a tag of the library, possibly specified as a tag name passed through an environment variable.
Another option would be to include the source of the C library in my project, but I was thinking if the users of my crate want to use a different (but compatible) version of the 3rd party library with my crate, they wouldn't be able to do so as easily.
So how are others in the community handling situations like this?
In general, you want to create a libfoo-sys crate. That crate will have a build script that compiles the native library and sets up the linker options.
The build script can use build-time dependencies like the cc crate to make the process of downloading and compiling the native library easier.
You can use environment variables or features to choose where the native library comes from. You could use one already installed by the user by their system package manager (or perhaps a hand-compiled version), you could download the source from somewhere, you could include the code in the repository, or you could use a git submodule to reference another git repository instead of actually copying code.
In many cases, you will also use a tool like rust-bindgen to create the "raw" Rust bindings for the C library.

How to access current cargo profile (build, test, bench, doc, ....) from the build script (build.rs)

I want to write a custom build.rs script that generates some diagrams to accompany the documentation for a crate I'm working on. I want this script to run only when I run cargo doc, not the other profiles (cargo build, cargo test, ...). What would be the best way to do that?
I was hoping that cargo would pass this info to build.rs in the PROFILE env variable, but that seems to only contain "debug" or "release".
This is not possible as of Rust 1.47. Cargo issue #4001 tracks the possibility of supporting this in some fashion.

Using Istanbul for integration tests against a Node microservice

Documentation is pretty sparse on doing coverage with istanbul for integration tests. When I run through my mocha tests, I get No coverage information was collected, exit without writing coverage information.
The first thing I do is instrument all my source code:
✗ istanbul instrument . -o .instrument
In my case, this is a REST microservice that is Dockerized which I have written Mocha tests to run against it to validate it once it is deployed. My expectation is istanbul will give me code coverage against the source from that Node service.
The second step I do this command to run node on my instrumented code:
✗ istanbul cover --report none .instrument/server.js
After that, I run my tests using the following from the my main src directory as follows (with results):
✗ istanbul cover --report none --dir coverage/unit node_modules/.bin/_mocha -- -R spec ./.instrument/test/** --recursive
swagger-tests
#createPet
✓ should add a new pet (15226ms)
#getPets
✓ should exist and return an Array (2378ms)
✓ should have at least 1 pet in list (2500ms)
✓ should return error if search not name or id
✓ should be sorted by ID (3041ms)
✓ should be sorted by ID even if no parameter (2715ms)
✓ should be only available pets (2647ms)
#getPetsSortedByName
✓ should be sorted by name (85822ms)
#deletePet
✓ should delete a pet (159ms)
9 passing (2m)
No coverage information was collected, exit without writing coverage information
When I run istanbul report, it obviously has nothing to report on.
What am I missing?
See develop branch of this project to reproduce issue.
The owner of istanbul helped me to resolve this. I was able to get things going by performing the following steps:
Skip instrumenting the code; it's not needed
Call istanbul with --handle-sigint as #heckj recommended and remove the flag --report none
Once your server is up, just run tests as normal: ./node_modules/.bin/_mocha -R spec ./test/** --recursive
Shutdown the server from step 2 to output the coverage
View the HTML file in open coverage/lcov-report/index.html
This looks like you were following the blog post I was just looking at when trying to figure out how to attack this time problem:
Javascript Integration Tests Coverage with Istanbul
I don't what specifically what is different between what you've posted above, and what that blog post identifies. One thing to check is to make sure that there are coverage*.json files getting generated when the code is being executed. I'm not sure when those files are specifically generated by Istanbul, so you may need to terminate the instrumented code running. There's also a mention of a --handle-sigint option on the cover command in the README that hinted at needing to invoke a manual SIGINT interupt to get coverage information on a long running process.
Looking at one of the bugs, there's obviously been some pain with this in the past, and some versions of istanbul had problems with "use strict" mode in the NodeJS code.
So my recommendation is run all the tests, and then make sure the processes are all terminated, before running the report command, and checking to see if the coverage*.json files are written somewhere. Beyond that, might make sense to take this as an issue into the github repo, where there appears to be good activity and answers.

Resources