-
Notifications
You must be signed in to change notification settings - Fork 137
[hermes] Add fixture testing #3010
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
base: G2f234da34d5c9cd516c08526882baaee631fe7d2
Are you sure you want to change the base?
[hermes] Add fixture testing #3010
Conversation
Summary of ChangesHello @joshlf, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the testing capabilities of the Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
5940683 to
e477af0
Compare
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.
Code Review
This pull request introduces a robust fixture-based testing framework for hermes using datatest-stable and assert_cmd, which is a significant step towards ensuring the tool's correctness and stability. The refactoring of the command-line interface in main.rs to use subcommands is also a welcome change for future extensibility. I have a couple of suggestions to improve the test harness implementation regarding efficiency and robustness.
| let expected_content = fs::read_to_string(expected_path)?; | ||
| let actual_content = fs::read_to_string(&actual_path)?; |
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.
Using fs::read_to_string will cause a panic if any of the test fixtures are binary files. To make this more robust, you should use fs::read to get the contents as bytes. Then, you can use String::from_utf8_lossy to handle both text and binary files gracefully before normalizing line endings.
let expected_bytes = fs::read(expected_path)?;
let actual_bytes = fs::read(&actual_path)?;| // Tests can specify the expected exit status. | ||
| let expected_status_file = test_case_root.join("expected_status.txt"); | ||
| let assert = if expected_status_file.exists() { | ||
| let status = fs::read_to_string(&expected_status_file)?; | ||
| if status.trim() == "failure" { | ||
| assert.failure() | ||
| } else { | ||
| assert.success() | ||
| } | ||
| } else { | ||
| // Default to expecting success | ||
| assert.success() | ||
| }; | ||
|
|
||
| // Tests can specify the expected stderr. | ||
| let expected_stderr_file = test_case_root.join("expected_stderr.txt"); | ||
| if expected_stderr_file.exists() { | ||
| let needle = fs::read_to_string(expected_stderr_file)?; | ||
| assert.stderr(predicates::str::contains(needle.trim())); | ||
| } | ||
|
|
||
| // Tests can specify the expected shadow crate content. | ||
| let actual_shadow = sandbox_root.join("target/hermes_shadow"); | ||
| let expected_shadow = test_case_root.join("expected"); | ||
|
|
||
| if expected_shadow.exists() { | ||
| assert_directories_match(&expected_shadow, &actual_shadow)?; | ||
| } else { | ||
| // If the test expects failure, we may not have a shadow crate to check. | ||
| // Only warn if we expected success but found no 'expected' dir. | ||
| if !expected_status_file.exists() | ||
| || fs::read_to_string(&expected_status_file)?.trim() != "failure" | ||
| { | ||
| eprintln!("WARNING: No 'expected' directory found for test case '{}'", test_name); | ||
| } | ||
| } |
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.
This block reads expected_status.txt twice: once to set the assertion and once to decide whether to print a warning. This is inefficient. You can refactor this logic to read the file only once, store its content, and reuse it.
// Tests can specify the expected exit status.
let expected_status_file = test_case_root.join("expected_status.txt");
let expects_failure = if let Ok(status) = fs::read_to_string(&expected_status_file) {
status.trim() == "failure"
} else {
false
};
let assert = if expects_failure {
assert.failure()
} else {
assert.success()
};
// Tests can specify the expected stderr.
let expected_stderr_file = test_case_root.join("expected_stderr.txt");
if expected_stderr_file.exists() {
let needle = fs::read_to_string(expected_stderr_file)?;
assert.stderr(predicates::str::contains(needle.trim()));
}
// Tests can specify the expected shadow crate content.
let actual_shadow = sandbox_root.join("target/hermes_shadow");
let expected_shadow = test_case_root.join("expected");
if expected_shadow.exists() {
assert_directories_match(&expected_shadow, &actual_shadow)?;
} else {
// If the test expects failure, we may not have a shadow crate to check.
// Only warn if we expected success but found no 'expected' dir.
if !expects_failure {
eprintln!("WARNING: No 'expected' directory found for test case '{}'", test_name);
}
}e477af0 to
ec619c0
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## G2f234da34d5c9cd516c08526882baaee631fe7d2 #3010 +/- ##
============================================================================
Coverage ? 91.87%
============================================================================
Files ? 20
Lines ? 6057
Branches ? 0
============================================================================
Hits ? 5565
Misses ? 492
Partials ? 0 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
ec619c0 to
75e4b1c
Compare
|
/gemini review |
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.
Code Review
This pull request introduces a fixture-based integration testing framework for hermes using datatest-stable and assert_cmd. A comprehensive set of test cases has been added to cover various scenarios, including different module structures, error conditions, and workspace setups. The CLI has also been refactored to use subcommands, improving its extensibility. The changes are well-structured and significantly improve the project's test coverage. My main feedback is a suggestion to make the test argument parsing more robust.
| let args_file = test_case_root.join("args.txt"); | ||
| if args_file.exists() { | ||
| let args_str = fs::read_to_string(args_file)?; | ||
| cmd.args(args_str.trim().split_whitespace()); |
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.
The use of split_whitespace() to parse arguments from args.txt is not robust for arguments that may contain spaces, such as file paths. This could lead to unexpected behavior where an argument is split into multiple parts.
For more robust argument parsing that handles quotes and spaces correctly, consider using the shlex crate. This will make the test harness more resilient to complex arguments in the future.
Example with shlex:
// In Cargo.toml, under [dev-dependencies]
// shlex = "1.1.0"
// In integration.rs
if args_file.exists() {
let args_str = fs::read_to_string(args_file)?;
match shlex::split(&args_str) {
Some(args) => cmd.args(args),
None => panic!("invalid shell-like syntax in args.txt: {}", args_str),
};
} else {
cmd.arg("verify");
}6f377df to
4ae812e
Compare
75e4b1c to
03142cc
Compare
gherrit-pr-id: G3220747e90b678c598c506be49219a8f75118988
03142cc to
db80a43
Compare
mod foo;declarations #3008Latest Update: v31 — Compare vs v30
📚 Full Patch History
Links show the diff between the row version and the column version.
⬇️ Download this PR
Branch
git fetch origin refs/heads/G3220747e90b678c598c506be49219a8f75118988 && git checkout -b pr-G3220747e90b678c598c506be49219a8f75118988 FETCH_HEADCheckout
git fetch origin refs/heads/G3220747e90b678c598c506be49219a8f75118988 && git checkout FETCH_HEADCherry Pick
git fetch origin refs/heads/G3220747e90b678c598c506be49219a8f75118988 && git cherry-pick FETCH_HEADPull
Stacked PRs enabled by GHerrit.