diff --git a/R/S4.R b/R/S4.R index 48174553..bd1b023c 100644 --- a/R/S4.R +++ b/R/S4.R @@ -656,15 +656,6 @@ find_package_with_symbol <- function(name, env, exclude = NULL) { } } -S4_remove_classes <- function(classes, where = parent.frame()) { - where <- topenv(where) - for (class in classes) { - if (methods::isClass(class, where = where)) { - methods::removeClass(class, where) - } - } -} - globalVariables(c( ".Data", "className", diff --git a/tests/testthat/helper.R b/tests/testthat/helper.R index 6248d70d..f0335f68 100644 --- a/tests/testthat/helper.R +++ b/tests/testthat/helper.R @@ -95,21 +95,18 @@ package_hooks <- function(package, event = "onLoad") { Filter(function(hook) !is_ide_hook(hook), hooks) } -local_S4_class <- function( - name, - ..., - env = parent.frame(), - where = topenv(env) -) { - out <- methods::setClass(name, ..., where = where) - defer(S4_remove_classes(name, where), env) - out -} - -local_S4_union <- function(name, members, env = parent.frame()) { - out <- methods::setClassUnion(name, members, where = topenv(env)) - defer(S4_remove_classes(name, topenv(env)), env) - out +local_S4_classes <- function(env = parent.frame(), where = topenv(env)) { + old <- methods::getClasses(where = where, inherits = FALSE) + defer( + { + new <- setdiff(methods::getClasses(where = where, inherits = FALSE), old) + for (class in new) { + methods::removeClass(class, where = where) + } + }, + env + ) + invisible() } # Create a temporary library, prepend it to .libPaths(), and restore the diff --git a/tests/testthat/test-S4.R b/tests/testthat/test-S4.R index 4a705a5b..26f320ab 100644 --- a/tests/testthat/test-S4.R +++ b/tests/testthat/test-S4.R @@ -1,10 +1,29 @@ test_that("can work with classGenerators", { - Foo := local_S4_class() + local_S4_classes() + Foo <- setClass("Foo") expect_equal(S4_to_S7_class(Foo), getClass("Foo")) }) +test_that("local_S4_classes cleans up S4 classes registered during scope", { + env <- new.env(parent = globalenv()) + + local({ + local_S4_classes(where = env) + setClass("CleanupClass", where = env) + setClassUnion("CleanupUnion", "CleanupClass", where = env) + setOldClass(c("CleanupOldChild", "CleanupOld"), where = env) + + expect_setequal( + methods::getClasses(where = env, inherits = FALSE), + c("CleanupClass", "CleanupUnion", "CleanupOldChild", "CleanupOld") + ) + }) + + expect_equal(methods::getClasses(where = env, inherits = FALSE), character()) +}) + test_that("S4_register registers an S7 class so it can be used with S4 methods", { - defer(S4_remove_classes("S4regS7")) + local_S4_classes() S4regS7 := new_class(package = NULL) S4regS7_S4 <- S4_register(S4regS7) expect_equal(S4regS7_S4, "S4regS7") @@ -12,7 +31,7 @@ test_that("S4_register registers an S7 class so it can be used with S4 methods", }) test_that("S4_contains requires prior S4 registration", { - on.exit(S4_remove_classes("S4regContainsUnregistered")) + local_S4_classes() S4regContainsUnregistered := new_class(package = NULL) expect_error( @@ -29,7 +48,7 @@ test_that("S4_contains requires prior S4 registration", { }) test_that("S4_register registers S4 old classes as virtual S7_object descendants", { - on.exit(S4_remove_classes(c("S4regParent", "S4regS7New"))) + local_S4_classes() setClass("S4regParent", slots = list(x = "numeric")) S4regS7New <- new_class( "S4regS7New", @@ -47,7 +66,7 @@ test_that("S4_register registers S4 old classes as virtual S7_object descendants }) test_that("S4_register registers an S3 class so it can be used with S4 methods", { - defer(S4_remove_classes(c("S4regS3a", "S4regS3b"))) + local_S4_classes() S4regS3_S4 <- S4_register(new_S3_class(c("S4regS3a", "S4regS3b"))) expect_equal(S4regS3_S4, "S4regS3a") # Must not extend S7_object — that was a silent bug pre-fix @@ -58,14 +77,11 @@ test_that("S4_register registers an S3 class so it can be used with S4 methods", }) test_that("S4_register registers an S7 union so it can be used with S4 methods", { - on.exit({ + local_S4_classes() + defer({ if (methods::isGeneric("S4regUnionGeneric")) { methods::removeGeneric("S4regUnionGeneric") } - S4_remove_classes(c( - "S4regUnionFoo", - "S4regUnionFoo_OR_character" - )) }) S4regUnionFoo <- new_class("S4regUnionFoo", package = NULL) @@ -85,15 +101,11 @@ test_that("S4_register registers an S7 union so it can be used with S4 methods", }) test_that("S4_register can reify S7 properties as slots for S4 subclasses", { - on.exit({ + local_S4_classes() + defer({ if (methods::isGeneric("S4regContainsGeneric")) { methods::removeGeneric("S4regContainsGeneric") } - S4_remove_classes(c( - "S4regContainsS4Child", - "S7::S4regContains", - "S7::S4regContainsChild" - )) }) S4regContains <- new_class( @@ -185,12 +197,7 @@ test_that("S4_register can reify S7 properties as slots for S4 subclasses", { }) test_that("S4_register constructs S4 subclasses of S7 classes that extend S4 classes", { - on.exit(S4_remove_classes(c( - "S4regNewParent", - "S4regNewMiddle", - "S4regNewChild", - "S4regNewGrandChild" - ))) + local_S4_classes() setClass( "S4regNewParent", slots = list(assays = "list", rowData = "character") @@ -283,14 +290,7 @@ test_that("S4_register constructs S4 subclasses of S7 classes that extend S4 cla }) test_that("S4_validate_class validates only matching S7 classes for S4 upcasts", { - on.exit(S4_remove_classes(c( - "S4regShimRoot", - "S4regShimParent", - "S4regShimChild", - "S4regShimGrandChild", - "S7::S4regShimParent", - "S7::S4regShimChild" - ))) + local_S4_classes() setClass("S4regShimRoot", slots = list(root = "numeric")) S4regShimParent <- new_class( @@ -324,14 +324,9 @@ test_that("S4_validate_class validates only matching S7 classes for S4 upcasts", }) test_that("S4_register registers abstract S7 classes as virtual S4 classes", { - on.exit({ + local_S4_classes() + defer({ try(methods::removeMethod("dim", "S4regAbstractConcrete"), silent = TRUE) - S4_remove_classes(c( - "S4regAbstractParent", - "S4regAbstract", - "S4regAbstractConcrete", - "S4regAbstractShim" - )) }) setClass("S4regAbstractParent", contains = "VIRTUAL") @@ -378,11 +373,7 @@ test_that("S4_register registers abstract S7 classes as virtual S4 classes", { }) test_that("S4_register uses S7 property defaults as S4 prototypes", { - on.exit(S4_remove_classes(c( - "S4regPrototype", - "S4regPrototypeChild", - "NULL_OR_character" - ))) + local_S4_classes() S4_register(NULL | class_character) S4regPrototype <- new_class( @@ -410,11 +401,7 @@ test_that("S4_register uses S7 property defaults as S4 prototypes", { }) test_that("S4_register treats S4 NULL slot sentinels as NULL-valued S7 properties", { - on.exit(S4_remove_classes(c( - "S4regNullable", - "S4regNullableChild", - "NULL_OR_character" - ))) + local_S4_classes() S4_register(NULL | class_character) S4regNullable <- new_class( @@ -447,12 +434,7 @@ test_that("S4_register treats S4 NULL slot sentinels as NULL-valued S7 propertie }) test_that("S4_contains rejects properties with custom accessors", { - on.exit(S4_remove_classes(c( - "S4regContainsDynamicChild", - "S7::S4regContainsDynamic", - "S4regContainsSetterChild", - "S7::S4regContainsSetter" - ))) + local_S4_classes() S4regContainsDynamic <- new_class( "S4regContainsDynamic", @@ -504,10 +486,7 @@ test_that("S4_contains rejects properties with custom accessors", { }) test_that("S4_register uses registered S7 unions as S4 slots", { - on.exit(S4_remove_classes(c( - "S7::S4regContainsUnion", - "integer_OR_numeric_OR_character" - ))) + local_S4_classes() S4regContainsUnion <- new_class( "S4regContainsUnion", @@ -530,15 +509,7 @@ test_that("S4_register uses registered S7 unions as S4 slots", { test_that("S4_register uses matching S4 unions as S4 slots", { env <- topenv(environment()) - on.exit(S4_remove_classes( - c( - "S4regContainsExistingUnion", - "S4regExistingUnion", - "S4regUnionMember2", - "S4regUnionMember1" - ), - env - )) + local_S4_classes(where = env) setClass("S4regUnionMember1", where = env) setClass("S4regUnionMember2", where = env) @@ -586,17 +557,18 @@ test_that("converts S4 base classes to S7 base classes", { }) test_that("converts S4 unions to S7 unions", { - Foo1 := local_S4_class(slots = "x") - Foo2 := local_S4_class(slots = "x") + local_S4_classes() + setClass("Foo1", slots = "x") + setClass("Foo2", slots = "x") - Union1 := local_S4_union(c("Foo1", "Foo2")) + setClassUnion("Union1", c("Foo1", "Foo2")) expect_equal( S4_to_S7_class(getClass("Union1")), new_union(getClass("Foo1"), getClass("Foo2")) ) - Foo3 := local_S4_class(slots = "x") - Union2 := local_S4_union(c("Union1", "Foo3")) + setClass("Foo3", slots = "x") + setClassUnion("Union2", c("Union1", "Foo3")) expect_equal( S4_to_S7_class(getClass("Union2")), new_union(getClass("Foo1"), getClass("Foo2"), getClass("Foo3")) @@ -605,14 +577,7 @@ test_that("converts S4 unions to S7 unions", { test_that("S4 slot properties convert S4 class unions to S7 unions", { env <- topenv(environment()) - on.exit(S4_remove_classes( - c( - "S4regUnionSlotChild", - "S4regUnionSlotParent", - "S4regUnionSlot" - ), - env - )) + local_S4_classes(where = env) setClassUnion("S4regUnionSlot", c("character", "NULL"), where = env) setClass( @@ -647,7 +612,7 @@ test_that("errors on non-S4 classes", { }) test_that("S7 classes can extend S4 classes", { - on.exit(S4_remove_classes(c("Parent", "Child"))) + local_S4_classes() setClass("Parent", slots = list(x = "numeric")) Child <- new_class( @@ -703,12 +668,7 @@ test_that("S7 classes can extend S4 classes", { }) test_that("S7 constructors dispatch to S4 parent initialize methods", { - defer(S4_remove_classes(c( - "S4regParentInitialize", - "S4regChildInitialize", - "S4regVirtualInitialize", - "S4regVirtualChildInitialize" - ))) + local_S4_classes() setClass("S4regParentInitialize", slots = list(x = "ANY", y = "matrix")) setMethod( "initialize", @@ -762,10 +722,7 @@ test_that("S7 constructors dispatch to S4 parent initialize methods", { }) test_that("S7 classes can not override S4 slots with custom accessors", { - defer(S4_remove_classes(c( - "S4regAccessorParent", - "S4regAccessorMiddle" - ))) + local_S4_classes() setClass("S4regAccessorParent", slots = list(x = "numeric")) expect_error( @@ -801,11 +758,7 @@ test_that("S7 classes can not override S4 slots with custom accessors", { }) test_that("S4 initialization sets S4 slots on subclasses of S7 classes", { - on.exit(S4_remove_classes(c( - "ParentForSlots", - "ChildForSlots", - "S4ChildForSlots" - ))) + local_S4_classes() setClass("ParentForSlots", slots = list(x = "numeric")) ChildForSlots <- new_class( @@ -837,7 +790,7 @@ test_that("S4 initialization sets S4 slots on subclasses of S7 classes", { }) test_that("@<- sets S4-only slots on subclasses of S7 classes", { - on.exit(S4_remove_classes(c("ParentForAt", "ChildForAt", "S4ChildForAt"))) + local_S4_classes() setClass("ParentForAt", slots = list(x = "numeric")) ChildForAt <- new_class( @@ -862,7 +815,7 @@ test_that("@<- sets S4-only slots on subclasses of S7 classes", { }) test_that("S4 initialize supports S3 data parts", { - on.exit(S4_remove_classes(c("ParentNum", "ChildNum"))) + local_S4_classes() setClass("ParentNum", contains = "numeric", slots = list(y = "character")) ChildNum <- new_class( @@ -885,7 +838,7 @@ test_that("S4 initialize supports S3 data parts", { }) test_that("S4 classes can not extend S7-over-S4 classes with property setters", { - on.exit(S4_remove_classes(c("Parent2", "Child2", "S4Child2"))) + local_S4_classes() setClass("Parent2", slots = list(x = "numeric")) Child2 <- new_class( @@ -915,14 +868,16 @@ test_that("S4 classes can not extend S7-over-S4 classes with property setters", test_that("S4_class_dispatch returns name of base class", { - Foo1 := local_S4_class(slots = list("x" = "numeric")) + local_S4_classes() + setClass("Foo1", slots = list("x" = "numeric")) expect_equal(S4_class_dispatch("Foo1"), "S4/S7::Foo1") }) test_that("S4_class_dispatch respects single inheritance hierarchy", { - Foo1 := local_S4_class(slots = list("x" = "numeric")) - Foo2 := local_S4_class(contains = "Foo1") - Foo3 := local_S4_class(contains = "Foo2") + local_S4_classes() + setClass("Foo1", slots = list("x" = "numeric")) + setClass("Foo2", contains = "Foo1") + setClass("Foo3", contains = "Foo2") expect_equal( S4_class_dispatch("Foo3"), c("S4/S7::Foo3", "S4/S7::Foo2", "S4/S7::Foo1") @@ -930,11 +885,12 @@ test_that("S4_class_dispatch respects single inheritance hierarchy", { }) test_that("S4_class_dispatch performs breadth first search for multiple dispatch", { - Foo1a := local_S4_class(slots = list("x" = "numeric")) - Foo1b := local_S4_class(contains = "Foo1a") - Foo2a := local_S4_class(slots = list("x" = "numeric")) - Foo2b := local_S4_class(contains = "Foo2a") - Foo3 := local_S4_class(contains = c("Foo1b", "Foo2b")) + local_S4_classes() + setClass("Foo1a", slots = list("x" = "numeric")) + setClass("Foo1b", contains = "Foo1a") + setClass("Foo2a", slots = list("x" = "numeric")) + setClass("Foo2b", contains = "Foo2a") + setClass("Foo3", contains = c("Foo1b", "Foo2b")) expect_equal( S4_class_dispatch("Foo3"), c( @@ -948,15 +904,16 @@ test_that("S4_class_dispatch performs breadth first search for multiple dispatch }) test_that("S4_class_dispatch handles extensions of base classes", { - Foo1 := local_S4_class(contains = "character") + local_S4_classes() + setClass("Foo1", contains = "character") expect_equal(S4_class_dispatch("Foo1"), c("S4/S7::Foo1", "character")) }) test_that("S4_class_dispatch handles extensions of S3 classes", { + local_S4_classes() setOldClass(c("Soo1", "Soo")) - defer(S4_remove_classes("Soo1")) - Foo2 := local_S4_class(contains = "Soo1") - Foo3 := local_S4_class(contains = "Foo2") + setClass("Foo2", contains = "Soo1") + setClass("Foo3", contains = "Foo2") expect_equal( S4_class_dispatch("Foo3"), c("S4/S7::Foo3", "S4/S7::Foo2", "Soo1", "Soo") @@ -964,17 +921,18 @@ test_that("S4_class_dispatch handles extensions of S3 classes", { }) test_that("S4_class_dispatch ignores unions", { - Foo1 := local_S4_class(slots = list("x" = "numeric")) - Foo2 := local_S4_class(slots = list("x" = "numeric")) - Foo3 := local_S4_union(c("Foo1", "Foo2")) + local_S4_classes() + setClass("Foo1", slots = list("x" = "numeric")) + setClass("Foo2", slots = list("x" = "numeric")) + setClassUnion("Foo3", c("Foo1", "Foo2")) expect_equal(S4_class_dispatch("Foo1"), "S4/S7::Foo1") expect_equal(S4_class_dispatch("Foo2"), "S4/S7::Foo2") }) test_that("S4_class_dispatch dispatches through the full S3 old-class hierarchy", { + local_S4_classes() setOldClass(c("S4OldS3a", "S4OldS3b")) - defer(S4_remove_classes(c("S4OldS3Child", "S4OldS3a", "S4OldS3b"))) setClass("S4OldS3Child", contains = "S4OldS3a") generic <- new_generic("S4OldS3Generic", "x") @@ -987,33 +945,30 @@ test_that("S4_class_dispatch dispatches through the full S3 old-class hierarchy" }) test_that("S4_class_dispatch includes virtual classes", { - Foo1 := local_S4_class() - Foo2 := local_S4_class(contains = "Foo1") + local_S4_classes() + setClass("Foo1") + setClass("Foo2", contains = "Foo1") expect_equal(S4_class_dispatch("Foo1"), "S4/S7::Foo1") expect_equal(S4_class_dispatch("Foo2"), c("S4/S7::Foo2", "S4/S7::Foo1")) }) test_that("S4_class_dispatch captures explicit package name", { - Foo1 := local_S4_class(package = "pkg") + local_S4_classes() + setClass("Foo1", package = "pkg") expect_equal(S4_class_dispatch("Foo1"), "S4/pkg::Foo1") }) test_that("S4_class_dispatch captures implicit package name", { env <- new.env() env$.packageName <- "mypkg" - Foo1 := local_S4_class(where = env) + local_S4_classes(where = env) + setClass("Foo1", where = env) expect_equal(S4_class_dispatch("Foo1"), "S4/mypkg::Foo1") }) test_that("S7 class extending S4 class with multiple parents works", { - on.exit(S4_remove_classes(c( - "MultiParent1", - "MultiParent2", - "MultiChild", - "S7MultiChild", - "S7MultiChild2" - ))) + local_S4_classes() setClass("MultiParent1", slots = list(x = "numeric")) setClass("MultiParent2", slots = list(y = "numeric")) diff --git a/tests/testthat/test-class-spec.R b/tests/testthat/test-class-spec.R index 10f118ce..d1cb05c4 100644 --- a/tests/testthat/test-class-spec.R +++ b/tests/testthat/test-class-spec.R @@ -215,10 +215,11 @@ test_that("can work with S7 classes that extend S3 classes", { # S4 ---------------------------------------------------------------------- test_that("can work with S4 classes", { - Foo1 := local_S4_class(contains = "character") - Foo2 := local_S4_class(contains = "Foo1") - Foo3 := local_S4_class(slots = list(x = "numeric")) - Foo4 := local_S4_class(contains = c("Foo2", "Foo3")) + local_S4_classes() + setClass("Foo1", contains = "character") + setClass("Foo2", contains = "Foo1") + setClass("Foo3", slots = list(x = "numeric")) + setClass("Foo4", contains = c("Foo2", "Foo3")) klass <- methods::getClass("Foo4") diff --git a/tests/testthat/test-class.R b/tests/testthat/test-class.R index 04a9eb8f..bc63d0d0 100644 --- a/tests/testthat/test-class.R +++ b/tests/testthat/test-class.R @@ -61,7 +61,8 @@ test_that("S7 classes check inputs", { }) test_that("S7 classes can inherit from S4 but not class unions", { - parentS4 := local_S4_class(slots = c(x = "numeric")) + local_S4_classes() + parentS4 <- setClass("parentS4", slots = c(x = "numeric")) child <- new_class("test", parent = parentS4, package = NULL) expect_s3_class(child, "S7_class") @@ -99,8 +100,9 @@ test_that("inheritance lets child properties narrow the parent's type", { }) test_that("inheritance lets child properties narrow with S4 inheritance", { - S4PropertyParent := local_S4_class(slots = c(x = "numeric")) - S4PropertyChild := local_S4_class(contains = "S4PropertyParent") + local_S4_classes() + S4PropertyParent <- setClass("S4PropertyParent", slots = c(x = "numeric")) + S4PropertyChild <- setClass("S4PropertyChild", contains = "S4PropertyParent") Parent := new_class( properties = list(x = S4PropertyParent), @@ -117,8 +119,9 @@ test_that("inheritance lets child properties narrow with S4 inheritance", { }) test_that("inheritance lets S7 children narrow S4 parent properties", { - Animal := local_S4_class() - Kennel := local_S4_class(slots = list(dog = "Animal")) + local_S4_classes() + Animal <- setClass("Animal") + Kennel <- setClass("Kennel", slots = list(dog = "Animal")) Dog := new_class(parent = Animal, package = NULL) DogKennel := new_class( @@ -132,10 +135,7 @@ test_that("inheritance lets S7 children narrow S4 parent properties", { }) test_that("inheritance lets S4 children narrow S7 parent properties", { - defer(S4_remove_classes(c( - "S4PropertyS7Parent", - "S4PropertyS7Child" - ))) + local_S4_classes() S4PropertyS7Parent := new_class(package = NULL) S4_register(S4PropertyS7Parent) diff --git a/tests/testthat/test-convert.R b/tests/testthat/test-convert.R index a9f011c1..11968f3a 100644 --- a/tests/testthat/test-convert.R +++ b/tests/testthat/test-convert.R @@ -137,7 +137,7 @@ test_that("fallback convert can convert to base type", { }) test_that("fallback convert can convert_up() an S4-derived S7 object to an S4 object", { - on.exit(S4_remove_classes(c("ParentS4", "ChildS7"))) + local_S4_classes() setClass("ParentS4", slots = list(x = "numeric")) ChildS7 <- new_class( @@ -156,7 +156,7 @@ test_that("fallback convert can convert_up() an S4-derived S7 object to an S4 ob }) test_that("fallback convert can use explicit S4 coercion via methods::as", { - on.exit(S4_remove_classes(c("ParentS4", "ChildS7", "UnrelatedS4"))) + local_S4_classes() setClass("ParentS4", slots = list(x = "numeric")) setClass("UnrelatedS4", slots = list(z = "character")) diff --git a/tests/testthat/test-method-dispatch.R b/tests/testthat/test-method-dispatch.R index 23157b15..e820f435 100644 --- a/tests/testthat/test-method-dispatch.R +++ b/tests/testthat/test-method-dispatch.R @@ -36,9 +36,10 @@ test_that("single dispatch works for S3 objects", { }) test_that("single dispatch works for S4 objects", { + local_S4_classes() foo := new_generic("x") - my_S4 := local_S4_class(contains = "numeric") + my_S4 <- setClass("my_S4", contains = "numeric") method(foo, my_S4) <- function(x) "S4" expect_equal(foo(my_S4(1)), "S4") @@ -162,10 +163,11 @@ test_that("can dispatch on base 'union' types", { }) test_that("single dispatch fails with informative messages", { + local_S4_classes() fail := new_generic("x") foo := new_class(package = NULL) - Foo := local_S4_class(slots = list("x" = "numeric")) + Foo <- setClass("Foo", slots = list("x" = "numeric")) expect_snapshot(error = TRUE, { fail(TRUE) @@ -178,10 +180,11 @@ test_that("single dispatch fails with informative messages", { }) test_that("multiple dispatch fails with informative messages", { + local_S4_classes() fail := new_generic(c("x", "y")) foo := new_class() - Foo := local_S4_class(slots = list("x" = "numeric")) + Foo <- setClass("Foo", slots = list("x" = "numeric")) expect_snapshot(error = TRUE, { fail(TRUE) diff --git a/tests/testthat/test-method-ops.R b/tests/testthat/test-method-ops.R index ffdd69bc..6273f17f 100644 --- a/tests/testthat/test-method-ops.R +++ b/tests/testthat/test-method-ops.R @@ -44,13 +44,14 @@ test_that("Ops generics dispatch to S3 methods", { test_that("operator methods on S3/S4 classes work when neither operand is S7", { local_methods(base_ops[["+"]]) + local_S4_classes() class_foo <- new_S3_class("foo") foo <- structure(list(), class = "foo") method(`+`, list(class_foo, class_any)) <- function(e1, e2) "foo+any" expect_equal(foo + 10, "foo+any") - fooS4 := local_S4_class(contains = "character") + fooS4 <- setClass("fooS4", contains = "character") method(`+`, list(fooS4, class_any)) <- function(e1, e2) "fooS4+any" expect_equal(fooS4("x") + 10, "fooS4+any") @@ -77,7 +78,8 @@ test_that("operator bridge does not clobber an existing group method", { test_that("Ops generics dispatch to S7 methods for S4 classes", { local_methods(base_ops[["+"]]) - fooS4 := local_S4_class(contains = "character") + local_S4_classes() + fooS4 <- setClass("fooS4", contains = "character") fooS7 := new_class() method(`+`, list(fooS7, fooS4)) <- function(e1, e2) "S7-S4" diff --git a/tests/testthat/test-method-register-S3.R b/tests/testthat/test-method-register-S3.R index b8ba6c0d..f07e447b 100644 --- a/tests/testthat/test-method-register-S3.R +++ b/tests/testthat/test-method-register-S3.R @@ -56,14 +56,10 @@ test_that("can register S7 method for S3 generic with S3 class signature", { }) test_that("internal generics register S4 methods for S4-backed S7 classes", { - on.exit({ + local_S4_classes() + defer({ try(methods::removeMethod("dim", "S4regDimParent"), silent = TRUE) try(methods::removeMethod("dim", "S4regDimChild"), silent = TRUE) - S4_remove_classes(c( - "S4regDimParent", - "S4regDimChild", - "S4regDimShim" - )) }) setClass("S4regDimParent", contains = "VIRTUAL") @@ -87,13 +83,9 @@ test_that("internal generics register S4 methods for S4-backed S7 classes", { }) test_that("base closures register S4 methods for S4-backed S7 classes", { + local_S4_classes() defer({ try(methods::removeMethod("unlist", "S4regUnlistChild"), silent = TRUE) - S4_remove_classes(c( - "S4regUnlistParent", - "S4regUnlistChild", - "S4regUnlistShim" - )) }) setClass("S4regUnlistParent", contains = "VIRTUAL") @@ -119,7 +111,8 @@ test_that("base closures register S4 methods for S4-backed S7 classes", { }) test_that("internal replacement generics can register full S4 signatures", { - on.exit({ + local_S4_classes() + defer({ try( methods::removeMethod( "dimnames<-", @@ -127,11 +120,6 @@ test_that("internal replacement generics can register full S4 signatures", { ), silent = TRUE ) - S4_remove_classes(c( - "S4regDimnamesParent", - "S4regDimnamesChild", - "S4regDimnamesShim" - )) }) setClass("S4regDimnamesParent", contains = "VIRTUAL") @@ -161,10 +149,7 @@ test_that("internal replacement generics can register full S4 signatures", { }) test_that("sentinels for internal replacement generics keep full S4 signatures", { - on.exit(S4_remove_classes(c( - "S4regDimnamesSentinelParent", - "S4regDimnamesSentinelChild" - ))) + local_S4_classes() setClass("S4regDimnamesSentinelParent", contains = "VIRTUAL") S4regDimnamesSentinelChild <- new_class( @@ -183,13 +168,11 @@ test_that("sentinels for internal replacement generics keep full S4 signatures", package = NULL ) ) - on.exit( + defer( methods::removeMethod( "dimnames<-", c("S4regDimnamesSentinelChild", "list") - ), - add = TRUE, - after = FALSE + ) ) expect_true(methods::hasMethod( "dimnames<-", diff --git a/tests/testthat/test-method-register-S4.R b/tests/testthat/test-method-register-S4.R index 0867653a..7f2d3009 100644 --- a/tests/testthat/test-method-register-S4.R +++ b/tests/testthat/test-method-register-S4.R @@ -1,11 +1,11 @@ test_that("can register S7 method for S4 generic", { + local_S4_classes() methods::setGeneric("bar", function(x) standardGeneric("bar")) S4foo := new_class(package = NULL) expect_snapshot_error(method(bar, S4foo) <- function(x) "foo") S4_register(S4foo) - defer(S4_remove_classes("S4foo")) method(bar, S4foo) <- function(x) "foo" expect_equal(bar(S4foo()), "foo") @@ -43,11 +43,11 @@ test_that("S4 method registration on class_double catches actual doubles", { }) test_that("errors when unregistering from an S4 generic", { + local_S4_classes() methods::setGeneric("removeS4", function(x) standardGeneric("removeS4")) defer(suppressMessages(methods::removeGeneric("removeS4"))) S4foo := new_class(package = NULL) S4_register(S4foo) - defer(S4_remove_classes("S4foo")) method(removeS4, S4foo) <- function(x) "foo" expect_snapshot(method(removeS4, S4foo) <- NULL, error = TRUE) diff --git a/tests/testthat/test-property.R b/tests/testthat/test-property.R index efa5bcd1..74936731 100644 --- a/tests/testthat/test-property.R +++ b/tests/testthat/test-property.R @@ -451,8 +451,9 @@ test_that("new_property() displays nicely", { }) test_that("properties can be base, S3, S4, S7, or S7 union", { + local_S4_classes() class_S7 := new_class(package = NULL) - class_S4 := local_S4_class(slots = c(x = "numeric")) + class_S4 <- setClass("class_S4", slots = c(x = "numeric")) my_class := new_class( package = NULL, @@ -554,7 +555,9 @@ test_that("property validation runs the class's own validator", { }) test_that("property validation runs an S4 class's validity method", { - PosNum := local_S4_class( + local_S4_classes() + PosNum <- setClass( + "PosNum", slots = c(n = "numeric"), validity = function(object) { if (object@n <= 0) "n must be positive" else TRUE diff --git a/tests/testthat/test-super.R b/tests/testthat/test-super.R index d6c88042..049284b2 100644 --- a/tests/testthat/test-super.R +++ b/tests/testthat/test-super.R @@ -58,8 +58,9 @@ test_that("super() works with abstract S3 classes (#686)", { }) test_that("super() works with S4 objects", { - Foo1 := local_S4_class(representation(x = "numeric")) - Foo2 := local_S4_class(contains = "Foo1") + local_S4_classes() + setClass("Foo1", representation(x = "numeric")) + setClass("Foo2", contains = "Foo1") obj <- methods::new("Foo2", x = 5) gen := new_generic("x") diff --git a/tests/testthat/test-union.R b/tests/testthat/test-union.R index 0ace04ac..0e34de4e 100644 --- a/tests/testthat/test-union.R +++ b/tests/testthat/test-union.R @@ -35,17 +35,19 @@ test_that("base unions display as expected", { }) test_that("can construct from S3 and S4 classes", { - S4_union := local_S4_class() + local_S4_classes() + S4_union <- setClass("S4_union") u <- new_union(class_factor, S4_union) expect_equal(u$classes, list(class_factor, getClass("S4_union"))) }) test_that("can construct with |", { + local_S4_classes() foo := new_class() - Foo1 := local_S4_class(slots = list("x" = "numeric")) - Foo2 := local_S4_class(slots = list("x" = "numeric")) - Foo3 := local_S4_union(c("Foo1", "Foo2")) + Foo1 <- setClass("Foo1", slots = list("x" = "numeric")) + Foo2 <- setClass("Foo2", slots = list("x" = "numeric")) + Foo3 <- setClassUnion("Foo3", c("Foo1", "Foo2")) expect_equal(class_integer | class_double, class_numeric) expect_equal(class_integer | class_numeric, class_numeric)