-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move test harness to separate package #110
base: master
Are you sure you want to change the base?
Conversation
Allow both dotenvy and dotenvy_macro to make use of the test harness
The [`should_panic_without_expect`](https://rust-lang.github.io/rust-clippy/master/index.html#/should_panic_without_expect) pedantic lint is failing CI. The lint is not that useful given our small tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see this being very useful in creating test files, test text, and testing more complicated cases.
I would prefer if the usage of custom assert functions were minimized. Fallible functions such as Efb::add_env_file
should return Result
. The tests themselves can be written a Result
signature as well. A custom error type may be helpful here.
test_util/src/envfile.rs
Outdated
} | ||
|
||
/// Add a string without a newline | ||
pub fn add_str(&mut self, s: &str) -> &mut Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
push_str
may be more conventional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we change to push
or append
then the other "add" functions should follow suit.
So we'd have:
push_vars
push_var
push_str
push_strln
push_bytes
push_byte
Or the append
version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think less is better. I think of Efb
as a wrapper around a vector of bytes, with one convenience function, add_key_value
.
We shouldn't try to do too much by supporting both byte functions and string functions.
My suggestion is to implement some of the Vec
functions:
add_byte
-> push
add_bytes
-> extend_from_slice
add_str
-> extend_from_slice(s.as_bytes())
add_strln
-> can add a string and push the newline char
And implement the convenience functions:
add_key_value
-> add_var
add_vars
-> use a for loop with add_var
Test writers can use the Vec
API and the string-to-byte conversions they are already familiar with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, simpler is better. The majority of use cases would be pushing &str
, so I do think keeping that as push_str
is worthwhile. Therefore, push_bytes
makes sense as a corollary.
add_vars
does have a performance improvement to looping over add_var
. Looping will perform multiple allocations. BUT, I will concede that the majority of new tests will only have 3 vars max in an env file.
So I will remove it.
test_util/src/envfile.rs
Outdated
/// | ||
/// Represented as bytes to allow for advanced manipulation and BOM testing. | ||
#[derive(Debug, Default)] | ||
pub struct EnvFileBuilder { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan of the Builder
suffix, since it's too commonly used in the other context, i.e., describing the API design. I would suggest EnvFileAdv
, with "Adv" short for Advanced. Perhaps you can think of something better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some options:
EnvFileAdvCreator
EnvFileMaker
AdvancedEnvFile
I quite like the last one. The struct can be passed into init_with_env_file
and add_env_file
, so semantically it makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am good with either AdvancedEnvFile
or AdvEnvFile
. I personally prefer shorter names; they are more adventurous (AdventurousEnvFile
?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Efb
is such a good acronym though. EnvFileBuilder
has grown on me!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am currently simplifying this crate. Removing the "default" code I have come to realise this should just be called EnvFileContents
and be the primary way one is constructed.
A String
, &str
, Vec<u8>
, &[u8]
or EnvFileBuilder
, can already be passed to TestEnv::add_env_file
. So why not just call this EnvFileContents
as it will be the only way of constructing one besides just using the primitive types. Plus that's exactly what it is.
efc
is a pretty good acronym too ;)
Understood, I'll go ahead and add an error type. You're right for wanting the failed states to be as descriptive as possible. When these utilities were part of the test harness, it made sense to have custom panic messages. Now it is a separate package: errors are far more appropriate.
Perhaps if we removed the default |
To match env_var
- Clone - PartialEq - Eq - PartialEq to String and &str - PartialEq to Vec<u8> and &[u8] - AsRef<[u8]>
@sonro I added my comments on Would you rather wait for that before updating this PR further? |
The new API can still be tested with these utilities too! #[test]
fn existing_var_no_env_file() {
let mut testenv = TestEnv::init();
testenv.add_env_var("TEST_KEY", "test_val");
test_in_env(&testenv, || {
let safe_vars = dotenvy::load_all().unwrap(); // or whatever the api ends up being
let actual = safe_vars.get("TEST_KEY").unwrap();
assert_eq!("test_val", actual");
});
} Plus we need it to thoroughly test the existing API - deprecated or not. We shouldn't mind unsafety within the test harness as it already uses a mutex for thread safety. |
Let users of the test utils customize their own defaults
To better match Rust API guidelines
The test utilities, proposed in #58, shouldn't just be in one test suite. The harness can, and should, be used across the project. It could even be used outside of
dotenvy
entirely.This PR creates a new workspace member
dotenvy_test_util
- which contains the test harness along with its documentation.The new test suite itself is nearly finished, see #111.