google / googletest

GoogleTest - Google Testing and Mocking Framework

Home Page:https://google.github.io/googletest/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[FR]: Matcher for absl::StatusOr and std::expected

neg-c opened this issue · comments

Does the feature exist in the most recent commit?

No

Why do we need this feature?

Working on code bases that use C++23, std::expected is used extensively for error handling.
Having a matcher for it would help on testing.

Describe the proposal.

Similar to VariantWith() add a matcher that uses std::expected and it supports its monadic features.
Would be nice to check for compiler features.

Is the feature specific to an operating system, compiler, or build system version?

As of this writing, the big 4 compiler library features support it.

In case it gets approved, assign it to me

Interestingly enough, Optional() can be used.

enum class Error { boom };

std::expected<int, Error> something = 1;
EXPECT_THAT(something, testing::Optional(testing::Gt(0)));

std::expected<int, Error> something = std::unexpected(Error::boom);
EXPECT_EQ(something, std::unexpected(Error::boom));

Interestingly enough, Optional() can be used.

enum class Error { boom };

std::expected<int, Error> something = 1;
EXPECT_THAT(something, testing::Optional(testing::Gt(0)));

std::expected<int, Error> something = std::unexpected(Error::boom);
EXPECT_EQ(something, std::unexpected(Error::boom));

Thats weird, still believe there should be a dedicated macro

Thats weird, still believe there should be a dedicated macro

I agree, the Optional thing is a hacky workaround for now but I would want something like EXPECT_THAT(something, testing::Expected(some_val)) where DescribeNegationTo would indicate that either there was a failure (and describe the error object, if possible) or that it succeeded with an unexpected value.

For a more fluent approach, maybe there could be matchers like EXPECT_THAT(something, succeedsWith(successValMatcher)) or EXPECT_THAT(something, failsWith(errorValMatcher))

Similar to how the existing matchers for Optional and Variant are quite general (ie not bound to the std:: classes), I think it should be reasonable to write this matcher with sufficient generality to work with std::expected and other popular value-or-error types. See e.g., https://ned14.github.io/outcome/tutorial/advanced/interop/value-or-error/

We can assume

  • value()
  • error()
  • has_value()

and public typedefs value_type and error_type. I don't think we need to do any ADL free function stuff like with variant.

This should work with std::expected, TartanLlama tl::expected, Boost.Outcome outcome::result, Boost.System system::result etc

The matcher for absl::StatusOr will be released by the abseil-cpp project. Someone is working on it now, but it will take a while.

C++23 and std::expected is not supported yet. We do not want it implemented until C++23 is officially supported.

For a more fluent approach, maybe there could be matchers like EXPECT_THAT(something, succeedsWith(successValMatcher)) or EXPECT_THAT(something, failsWith(errorValMatcher))

I like this.
It's a little bit weird cuz absl version std::expected is StatusOr, there should be matcher name that will be understood by both library users.
Having it testing::Expected makes it a bit harder to read because of the EXPECTED_X macros.