1818# ' See [expect_vector()] for testing properties of objects created by vctrs.
1919# '
2020# ' @param type String giving base type (as returned by [typeof()]).
21- # ' @param class Either a character vector of class names, or
22- # ' for `expect_s3_class()` and `expect_s4_class()`, an `NA` to assert
23- # ' that `object` isn't an S3 or S4 object.
21+ # ' @param class
22+ # ' * `expect_type()`: a single string giving an R base type.
23+ # ' * `expect_s3_class()`: a character vector of class names or `NA` to assert
24+ # ' that `object` isn't an S3 object. If you provide multiple class names,
25+ # ' the test will pass if `object` inherits from any of them, unless
26+ # ' `exact = TRUE`.
27+ # ' * `expect_s4_class()`: a character vector of class names or `NA` to assert
28+ # ' that `object` isn't an S4 object.
29+ # ' * `expect_s7_class()`: an [S7::S7_class()] object.
2430# ' @inheritParams expect_that
2531# ' @family expectations
2632# ' @examples
3137# ' # A data frame is built from a list:
3238# ' expect_type(x, "list")
3339# '
40+ # ' f <- factor(c("a", "b", "c"))
41+ # ' o <- ordered(f)
42+ # '
43+ # ' # Using multiple class names tests if the object inherits from any of them
44+ # ' expect_s3_class(f, c("ordered", "factor"))
45+ # ' # Use exact = TRUE to test for exact match
46+ # ' show_failure(expect_s3_class(f, c("ordered", "factor"), exact = TRUE))
47+ # ' expect_s3_class(o, c("ordered", "factor"), exact = TRUE)
48+ # '
3449# ' # An integer vector is an atomic vector of type "integer"
3550# ' expect_type(x$x, "integer")
3651# ' # It is not an S3 object
@@ -66,8 +81,8 @@ expect_type <- function(object, type) {
6681# ' @export
6782# ' @rdname inheritance-expectations
6883# ' @param exact If `FALSE`, the default, checks that `object` inherits
69- # ' from `class`. If `TRUE`, checks that object has a class that's identical
70- # ' to `class`.
84+ # ' from any element of `class`. If `TRUE`, checks that object has a class
85+ # ' that's identical to `class`.
7186expect_s3_class <- function (object , class , exact = FALSE ) {
7287 check_bool(exact )
7388
@@ -106,35 +121,6 @@ expect_s3_class <- function(object, class, exact = FALSE) {
106121 pass(act $ val )
107122}
108123
109- # ' @export
110- # ' @rdname inheritance-expectations
111- expect_s7_class <- function (object , class ) {
112- check_installed(" S7" )
113- if (! inherits(class , " S7_class" )) {
114- stop_input_type(class , " an S7 class object" )
115- }
116-
117- act <- quasi_label(enquo(object ))
118-
119- if (! S7 :: S7_inherits(object )) {
120- return (fail(sprintf(" %s is not an S7 object" , act $ lab )))
121- }
122-
123- if (! S7 :: S7_inherits(object , class )) {
124- obj_class <- setdiff(base :: class(object ), " S7_object" )
125- class_desc <- paste0(" <" , obj_class , " >" , collapse = " /" )
126- msg <- sprintf(
127- " %s inherits from %s not <%s>." ,
128- act $ lab ,
129- class_desc ,
130- attr(class , " name" , TRUE )
131- )
132- return (fail(msg ))
133- }
134-
135- pass(act $ val )
136- }
137-
138124# ' @export
139125# ' @rdname inheritance-expectations
140126expect_s4_class <- function (object , class ) {
@@ -162,13 +148,40 @@ expect_s4_class <- function(object, class) {
162148 }
163149 }
164150 } else {
165- abort( " ` class` must be a NA or a character vector" )
151+ stop_input_type( class , c( " a character vector" , " NA " ) )
166152 }
167153
168154 pass(act $ val )
169155}
170156
171- isS3 <- function (x ) is.object(x ) && ! isS4(x )
157+ # ' @export
158+ # ' @rdname inheritance-expectations
159+ expect_s7_class <- function (object , class ) {
160+ check_installed(" S7" )
161+ if (! inherits(class , " S7_class" )) {
162+ stop_input_type(class , " an S7 class object" )
163+ }
164+
165+ act <- quasi_label(enquo(object ))
166+
167+ if (! S7 :: S7_inherits(object )) {
168+ return (fail(sprintf(" %s is not an S7 object" , act $ lab )))
169+ }
170+
171+ if (! S7 :: S7_inherits(object , class )) {
172+ obj_class <- setdiff(base :: class(object ), " S7_object" )
173+ class_desc <- paste0(" <" , obj_class , " >" , collapse = " /" )
174+ msg <- sprintf(
175+ " %s inherits from %s not <%s>." ,
176+ act $ lab ,
177+ class_desc ,
178+ attr(class , " name" , TRUE )
179+ )
180+ return (fail(msg ))
181+ }
182+
183+ pass(act $ val )
184+ }
172185
173186# ' Does an object inherit from a given class?
174187# '
@@ -177,15 +190,16 @@ isS3 <- function(x) is.object(x) && !isS4(x)
177190# '
178191# ' `expect_is()` is an older form that uses [inherits()] without checking
179192# ' whether `x` is S3, S4, or neither. Instead, I'd recommend using
180- # ' [expect_type()], [expect_s3_class()] or [expect_s4_class()] to more clearly
181- # ' convey your intent.
193+ # ' [expect_type()], [expect_s3_class()], or [expect_s4_class()] to more clearly
194+ # ' convey your intent.
182195# '
183196# ' @section 3rd edition:
184197# ' `r lifecycle::badge("deprecated")`
185198# '
186199# ' `expect_is()` is formally deprecated in the 3rd edition.
187200# '
188201# ' @keywords internal
202+ # ' @param class Class name passed to `inherits()`.
189203# ' @inheritParams expect_type
190204# ' @export
191205expect_is <- function (object , class , info = NULL , label = NULL ) {
@@ -212,6 +226,9 @@ expect_is <- function(object, class, info = NULL, label = NULL) {
212226 pass(act $ val )
213227}
214228
229+ # Helpers ----------------------------------------------------------------------
230+
231+ isS3 <- function (x ) is.object(x ) && ! isS4(x )
215232
216233format_class <- function (x ) {
217234 paste0(encodeString(x , quote = " '" ), collapse = " /" )
0 commit comments