mercredi 20 février 2019

Philosophy: What about using private utility functions and structs in integration tests?

So here's our situation. Our system (written in Rust) includes a DNS server, which it sets up on port 53 upon startup. This DNS server is contained in a submodule called entry_dns, at project/src/entry_dns/dns_socket_server.rs. Also in the entry_dns submodule are various private pieces of logic that are in production useful only to the entry_dns submodule and should not be accessible anywhere else. For example, there's a PacketFacade struct that is very helpful for both creating and parsing DNS packets.

We have an integration test for the DNS-server part of our system. This integration test starts the entire system, creates a couple of DNS requests, sends them to the server on port 53, collects the responses, and asserts on their contents.

So far, standard stuff, no surprises, no real questions.

Here come the questions.

I can think of several good reasons why the integration test should use the private PacketFacade struct from inside the entry_dns submodule to compose the test DNS requests and inspect the resulting responses. However, given that a Rust integration test is in a completely separate crate from the code it tests, and that even the non-entry_dns production code can't see PacketFacade, the integration test certainly can't see it, and we can't easily make PacketFacade available to the integration test without also making it visible to the production code, which we don't want.

We tried putting this in the top-level lib.rs file:

#[cfg(not(test))]
mod entry_dns
#[cfg(test)]
pub mod entry_dns

but the test still couldn't see the entry_dns submodule.

Do you have thoughts on either subject (either the philosophical acuity of using private production utility functions and structs in integration tests, or the more practical concept of how to do it in Rust, whether it's good or bad)?

Thanks!

Aucun commentaire:

Enregistrer un commentaire