Skip to content
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

testing: MockConnection helper for testing clients without a server #465

Merged
merged 2 commits into from Jul 16, 2022

Conversation

tdyas
Copy link
Contributor

@tdyas tdyas commented Mar 16, 2021

This PR adds MockConnection which implements crate::connection::ConnectionLike and crate::aio::ConnectionLike to appear like a client without the need to make any network requests. It is initialized with a list of MockCmd instances which wrap the expected commands and responses. This allows users to test their clients without much overhead.

The testing module is behind the testing feature which is non-default. Users should activate it in the dev-dependencies of their crate's Cargo.toml.

@tdyas
Copy link
Contributor Author

tdyas commented Mar 16, 2021

Open question: What would be the suggested way to test Pipeline with MockConnection?

@tdyas
Copy link
Contributor Author

tdyas commented May 19, 2021

I cleaned up the PR, added module docs with example, and made sure to test by enabling the aio feature. This should be ready for review. (I am using a variant of this code locally.)

@tdyas
Copy link
Contributor Author

tdyas commented Jun 8, 2021

cc @Marwes -- It was unclear to me how to flag a PR for attention so decided to cc you here. Is there a better way to go about getting attention for a PR? Are you the right person?

@tdyas
Copy link
Contributor Author

tdyas commented May 18, 2022

Rebased on latest main and force pushed.

Cargo.toml Outdated
@@ -68,6 +68,7 @@ script = ["sha1_smol"]
tls = ["native-tls"]
async-std-comp = ["aio", "async-std"]
async-std-tls-comp = ["async-std-comp", "async-native-tls", "tls"]
testing = ["futures"]
Copy link
Contributor

@djc djc May 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this intended to be part of the public API? What's the use case for doing this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is intended to be part of the public API so that users (like me) can incorporate these test helpers into the unit tests in our codebases. I have made it be a feature here (which would be enabled as a dev dependency), but it could also be put into a separate crate, much like Tokio has done with the tokio-test crate. Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A separate crate would allow evolving the API separately from the rest of the crate's API. I suppose we could keep the feature unstable for now (as in, we don't guarantee the public API to be compatible across semver-compatible versions of the crate).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will restructure this PR to create a redis-test crate. Is that acceptable?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jaymell what do you think? I'm just worried the API might be unstable, but maybe it's not so bad?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I would say that a separate crate certainly does sound like an ideal solution, though the additional maintenance costs there do temper my enthusiasm somewhat 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll switch to separate crate then (but the code will still live in this repo).

src/testing.rs Outdated
#[cfg(feature = "aio")]
use crate::aio::ConnectionLike as AioConnectionLike;

/// Helper trait for converting test values into a `redis::Value` returned from a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How/why is ToRedisArgs/FromRedisValue different from what we need here?

Copy link
Contributor Author

@tdyas tdyas May 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither ToRedisArgs nor FromRedisValue produces redis::Value instances from non-Redis values as required by the test helper:

  • ToRedisArgs cannot be used because it is designed to convert a value into an array of bytes and not convert to redis::Value. (ToRedisArgs.to_redis_args returns Vec<Vec<u8>> and ToRedisArgs.write_redis_args wants a RedisWrite impl which has methods like write_arg which takes a &[u8]).
  • FromRedisValue is irrelevant because it converts in the opposite direction than what is needed by the test helper. The test helper needs to convert from a non-Redis type to redis::Value. FromRedisValue converts from redis::Value to a non-Redis type.

@tdyas tdyas force-pushed the mock_connection branch 2 times, most recently from 873fa5b to d108f46 Compare May 24, 2022 05:19
@@ -10,6 +10,9 @@ documentation = "https://docs.rs/redis"
license = "BSD-3-Clause"
edition = "2018"

[workspace]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to find nested crate workspaces confusing to navigate. Would you mind changing this so that the top-level Cargo.toml only contains the workspace, and move the redis crate into a redis directory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should that be done in a separate PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(to avoid confusing commit history)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my mind the ideal way to submit it would be a single PR with clean commits: one commit that moves the code around and one commit that adds the new crate. Each commit should ideally pass CI, though I usually don't test that explicitly (but it sucks if formatting changes for one commit make it into another).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it sounds like that PRs are not squashed before merge then. Will do as separate commits in this PR then. (Context: My company merges via squash-and-merge generally for PRs so a separate PR would be the only way to accomplish having separate commit history in that case.)

Copy link
Contributor

@djc djc May 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also okay with separate PRs if you prefer. For my own changes I usually submit clean commits "manually" (squashing with interactive rebase). If a PR only contains one logical change, I'll also squash via merge in the Git UI, but I don't like doing that for changes that contain multiple logical changes.

@@ -0,0 +1,18 @@
[package]
name = "redis-test"
version = "0.21.5"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just call this 0.1.0.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

license = "BSD-3-Clause"

[dependencies]
redis = { path = ".." }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're going to publish this it should also have a specific version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a version, but kept the path so it continues to work with in-repo builds. Tokio does something similar.

redis-test/Cargo.toml Show resolved Hide resolved
@tdyas
Copy link
Contributor Author

tdyas commented May 30, 2022

I rebased the PR and turned it into two commits: the first moves the existing redis crate sources into a redis subdir, then second commit introduces the redis-test crate.

@tdyas tdyas force-pushed the mock_connection branch 2 times, most recently from aa0e40f to 340debd Compare May 30, 2022 22:33
@tdyas
Copy link
Contributor Author

tdyas commented May 30, 2022

The CI tests with Rust 1.51.0 fails due to async-std dependency async-global-executor using 2021 Edition.

Copy link
Contributor

@djc djc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you rebase this, I'd be okay with merging this.

Style nit: I think we could just git mv mock_conn.rs lib.rs, it doesn't make much sense to me to have the indirection in this case since everything lives in one module anyway.

@tdyas
Copy link
Contributor Author

tdyas commented Jul 4, 2022

Rebased and also moved the contents of redis_test::mock_conn into just redis_test.

@tdyas
Copy link
Contributor Author

tdyas commented Jul 4, 2022

Repushed after making sure subsequent updates to Cargo.toml were taken into account.

@tdyas
Copy link
Contributor Author

tdyas commented Jul 4, 2022

Note: The lint job in CI is failing on existing code, and not the new redis-test crate. https://github.com/redis-rs/redis-rs/runs/7183833699?check_suite_focus=true#step:6:40

@djc
Copy link
Contributor

djc commented Jul 5, 2022

@jaymell any thoughts before we merge this?

I'll take care of the new clippy issues separately.

@jaymell jaymell merged commit f7409d0 into redis-rs:main Jul 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants