| Crates.io | nutype_test_util |
| lib.rs | nutype_test_util |
| version | 0.1.3 |
| created_at | 2025-06-29 19:26:09.771431+00 |
| updated_at | 2025-06-29 21:57:36.981473+00 |
| description | Ergonomically create newtypes in tests |
| homepage | |
| repository | https://github.com/nik-rev/nutype-test-util |
| max_upload_size | |
| id | 1731044 |
| size | 40,104 |
nutype_test_utilnutype crate allows you to create newtypes in an ergonomic way. However, using these newtypes in tests leads to a lot of boilerplate:
// in `#[cfg(test)]`
Remote {
repo: Repo::try_new("helix-editor/helix").unwrap(),
pr_number: PrNumber::new(NonZeroU32::new(15).unwrap()),
commit: Some(Commit::try_new("1a2b3c4d").unwrap()),
}
Tests should be low-effort to write and you should not be punished this hard for wanting more type safety in your code.
This crate provides a proc macro#[nutype_test_util::derive(From)] which generates From impls for your newtypes. It makes the test syntax much easier to type:
// in `#[cfg(test)]`
Remote {
repo: "helix-editor/helix".into(),
pr_number: 15.into(),
commit: Some("1a2b3c4d".into()),
}
You use it like this:
#[nutype_test_util::derive(From)]
#[nutype(validate(non_empty))]
struct Repo(String);
#[nutype_test_util::derive(From)]
#[nutype]
struct PrNumber(NonZeroU32);
#[nutype_test_util::derive(From)]
#[nutype(validate(non_empty, predicate = is_valid_commit_hash))]
struct Commit(String)
The above generates code like this:
#[cfg(test)]
impl<T: Into<String>> ::core::convert::From<T> for Repo {
fn from(value: T) -> Self {
let value: String = value.into();
Self::try_new(value).unwrap()
}
}
#[cfg(test)]
impl<T: Into<u32>> ::core::convert::From<T> for PrNumber {
fn from(value: T) -> Self {
let value: u32 = value.into();
Self::new(::core::num::NonZeroU32::new(value).unwrap())
}
}
#[cfg(test)]
impl<T: Into<String>> ::core::convert::From<T> for Commit {
fn from(value: T) -> Self {
let value: String = value.into();
Self::try_new(value).unwrap()
}
}