diff --git a/R/BASiCSParams-methods.R b/R/BASiCSParams-methods.R
index 90243b242b89972c980b1294ef23f4c78ba5a060..55bc5de268c8f7f6794e7608205c8b28bb7f884f 100644
--- a/R/BASiCSParams-methods.R
+++ b/R/BASiCSParams-methods.R
@@ -68,7 +68,7 @@ setValidity("BASiCSParams", function(object) {
 })
 
 #' @rdname setParam
-setMethod("setParam", "BASiCSParams",function(object, name, value) {
+setMethod("setParam", "BASiCSParams", function(object, name, value) {
     checkmate::assertString(name)
 
     if (name == "nCells" || name == "nBatches") {
diff --git a/R/utils.R b/R/utils.R
index 39e770d8932c8bb185df020cbd45fc54bdf5a47a..0a9098758d0d6490b3749452eb1189717b071104 100644
--- a/R/utils.R
+++ b/R/utils.R
@@ -23,6 +23,9 @@ logistic <- function(x, x0, k) {
 #'         common columns.
 rbindMatched <- function(df1, df2) {
     common.names <- intersect(colnames(df1), colnames(df2))
+    if (length(common.names) < 2) {
+        stop("There must be at least two columns in common")
+    }
     combined <- rbind(df1[, common.names], df2[, common.names])
 
     return(combined)
diff --git a/tests/testthat/test-BASiCSParams.R b/tests/testthat/test-BASiCSParams.R
index 541abc15815caaa54b6f0ec4b5fff2c35e158e7b..97866e7e63fe6bbae2d8994faf9764526f806687 100644
--- a/tests/testthat/test-BASiCSParams.R
+++ b/tests/testthat/test-BASiCSParams.R
@@ -1,7 +1,12 @@
 context("BASiCSParams")
 
+params <- newBASiCSParams()
+
+test_that("printing works", {
+    expect_output(show(params), "A Params object of class BASiCSParams")
+})
+
 test_that("gene.params checks work", {
-    params <- newBASiCSParams()
     expect_error(setParam(params, "gene.params", data.frame(A = 1, B = 1)),
                  "gene.params: Incorrect column names")
     expect_error(setParam(params, "gene.params",
@@ -10,7 +15,6 @@ test_that("gene.params checks work", {
 })
 
 test_that("cell.params checks work", {
-    params <- newBASiCSParams()
     expect_error(setParam(params, "cell.params", data.frame(A = 1, B = 1)),
                  "cell.params: Incorrect column names")
     expect_error(setParam(params, "cell.params",
@@ -19,9 +23,14 @@ test_that("cell.params checks work", {
 })
 
 test_that("nBatches checks work", {
-    params <- newBASiCSParams()
     expect_error(setParam(params, "nCells", 1),
                  "nCells cannot be set directly, set batchCells instead")
     expect_error(setParam(params, "nBatches", 1),
                  "nBatches cannot be set directly, set batchCells instead")
 })
+
+test_that("batchCells checks work", {
+    pp <- setParam(params, "batchCells", c(10, 10))
+    expect_equal(getParam(pp, "nCells"), 20)
+    expect_equal(getParam(pp, "nBatches"), 2)
+})
diff --git a/tests/testthat/test-Lun2Params.R b/tests/testthat/test-Lun2Params.R
index 5fb60621ad864a0f04ae7f1b2297f7a2b37dc167..98d424f8f540f4a64a32dfadfe3925da0bc43111 100644
--- a/tests/testthat/test-Lun2Params.R
+++ b/tests/testthat/test-Lun2Params.R
@@ -1,7 +1,12 @@
 context("Lun2Params")
 
+params <- newLun2Params()
+
+test_that("printing works", {
+    expect_output(show(params), "A Params object of class Lun2Params")
+})
+
 test_that("nCells checks work", {
-    params <- newLun2Params()
     expect_error(setParam(params, "nCells", 1),
                  "nCells cannot be set directly, set cell.plates instead")
     expect_error(setParam(params, "nPlates", 1),
@@ -9,7 +14,6 @@ test_that("nCells checks work", {
 })
 
 test_that("gene.params checks work", {
-    params <- newLun2Params()
     expect_error(setParam(params, "gene.params", data.frame(A = 1, B = 1)),
                  "gene.params: Incorrect column names")
     expect_error(setParam(params, "gene.params",
diff --git a/tests/testthat/test-LunParams.R b/tests/testthat/test-LunParams.R
new file mode 100644
index 0000000000000000000000000000000000000000..5f5720bdc56cd62d78403410424748ea4b2b16ac
--- /dev/null
+++ b/tests/testthat/test-LunParams.R
@@ -0,0 +1,17 @@
+context("LunParams")
+
+params <- newLunParams()
+
+test_that("printing works", {
+    expect_output(show(params), "A Params object of class LunParams")
+})
+
+test_that("nCells checks work", {
+    expect_error(setParam(params, "nCells", 1),
+                 "nCells cannot be set directly, set groupCells instead")
+})
+
+test_that("nGroups checks work", {
+    expect_error(setParam(params, "nGroups", 1),
+                 "nGroups cannot be set directly, set groupCells instead")
+})
diff --git a/tests/testthat/test-MFAEstimate.R b/tests/testthat/test-MFAEstimate.R
new file mode 100644
index 0000000000000000000000000000000000000000..12cee5cc796b64d179c173e2f1b5583f2fb52edb
--- /dev/null
+++ b/tests/testthat/test-MFAEstimate.R
@@ -0,0 +1,9 @@
+context("MFAEstimate")
+
+library(scater)
+data("sc_example_counts")
+
+test_that("MFAEstimate works", {
+    params <- mfaEstimate(sc_example_counts)
+    expect_true(validObject(params))
+})
diff --git a/tests/testthat/test-MFAParams.R b/tests/testthat/test-MFAParams.R
new file mode 100644
index 0000000000000000000000000000000000000000..1cd9c19990ff0e3bf06c2c30532f23d828662738
--- /dev/null
+++ b/tests/testthat/test-MFAParams.R
@@ -0,0 +1,7 @@
+context("MFAParams")
+
+params <- newMFAParams()
+
+test_that("printing works", {
+    expect_output(show(params), "A Params object of class MFAParams")
+})
diff --git a/tests/testthat/test-PhenoParams.R b/tests/testthat/test-PhenoParams.R
index d5a252daba9f5f300840bc949f8a199b79d6e7a1..d806e99a73ea7b757954fdc0b56989e5ced38297 100644
--- a/tests/testthat/test-PhenoParams.R
+++ b/tests/testthat/test-PhenoParams.R
@@ -1,15 +1,20 @@
 context("PhenoParams")
 
+params <- newPhenoParams()
+
 test_that("constructor is valid", {
-    expect_true(validObject(newPhenoParams()))
+    expect_true(validObject(params))
+})
+
+test_that("printing works", {
+    expect_output(show(params), "A Params object of class PhenoParams")
 })
 
 test_that("nGenes checks work", {
-    params <- newPhenoParams()
     expect_error(setParam(params, "nGenes", 1),
                  "nGenes cannot be set directly")
-    params <- setParam(params, "n.de", 0)
-    total <- getParam(params, "n.de") + getParam(params, "n.pst") +
-             getParam(params, "n.pst.beta") + getParam(params, "n.de.pst.beta")
-    expect_equal(getParam(params, "nGenes"), total)
+    pp <- setParam(params, "n.de", 0)
+    total <- getParam(pp, "n.de") + getParam(pp, "n.pst") +
+             getParam(pp, "n.pst.beta") + getParam(pp, "n.de.pst.beta")
+    expect_equal(getParam(pp, "nGenes"), total)
 })
diff --git a/tests/testthat/test-SCDDParams.R b/tests/testthat/test-SCDDParams.R
index da4d061f8021462f833694061cdee509d35e4558..05ff5ef034d478516785e809e9d4edae650fca9d 100644
--- a/tests/testthat/test-SCDDParams.R
+++ b/tests/testthat/test-SCDDParams.R
@@ -1,17 +1,22 @@
 context("SCDDParams")
 
+params <- newSCDDParams()
+
 test_that("constructor is valid", {
-    expect_true(validObject(newSCDDParams()))
+    expect_true(validObject(params))
+})
+
+test_that("printing works", {
+    expect_output(show(params), "A Params object of class SCDDParams")
 })
 
 test_that("nGenes checks work", {
-    params <- newSCDDParams()
     expect_error(setParam(params, "nGenes", 1),
                  paste("nGenes cannot be set directly, set nDE, nDP, nDM, nDB,",
                        "nEE or nEP instead"))
-    params <- setParam(params, "nEE", 0)
-    total <- getParam(params, "nDE") + getParam(params, "nDP") +
-             getParam(params, "nDM") + getParam(params, "nDP") +
-             getParam(params, "nEE") + getParam(params, "nEP")
-    expect_equal(getParam(params, "nGenes"), total)
-})
\ No newline at end of file
+    pp <- setParam(params, "nEE", 0)
+    total <- getParam(pp, "nDE") + getParam(pp, "nDP") +
+             getParam(pp, "nDM") + getParam(pp, "nDP") +
+             getParam(pp, "nEE") + getParam(pp, "nEP")
+    expect_equal(getParam(pp, "nGenes"), total)
+})
diff --git a/tests/testthat/test-SCE-functions.R b/tests/testthat/test-SCE-functions.R
index 83e002d7ea3bf48c9fec6b1386ac5e8fa2eeb2c5..973cf545010fdb66ea3e9f80959e1115abde5a20 100644
--- a/tests/testthat/test-SCE-functions.R
+++ b/tests/testthat/test-SCE-functions.R
@@ -1,7 +1,26 @@
 context("SCE functions")
 
+sce <- simpleSimulate()
+
+test_that("addFeatureStats works with counts", {
+    ss <- addFeatureStats(sce)
+    expect_true(all(c("MeanCounts", "VarCounts", "CVCounts", "MedCounts",
+                      "MADCounts") %in% colnames(rowData(ss))))
+    ss <- addFeatureStats(sce, log = TRUE)
+    expect_true(all(c("MeanLogCounts", "VarLogCounts", "CVLogCounts",
+                      "MedLogCounts", "MADLogCounts") %in%
+                    colnames(rowData(ss))))
+    ss <- addFeatureStats(sce, no.zeros = TRUE)
+    expect_true(all(c("MeanCountsNo0", "VarCountsNo0", "CVCountsNo0",
+                      "MedCountsNo0", "MADCountsNo0") %in%
+                        colnames(rowData(ss))))
+    ss <- addFeatureStats(sce, log = TRUE, no.zeros = TRUE)
+    expect_true(all(c("MeanLogCountsNo0", "VarLogCountsNo0", "CVLogCountsNo0",
+                      "MedLogCountsNo0", "MADLogCountsNo0") %in%
+                        colnames(rowData(ss))))
+})
+
 test_that("addGeneLengths generate method works", {
-    sce <- simpleSimulate()
     expect_silent(addGeneLengths(sce))
     expect_error(addGeneLengths("a"))
     expect_error(addGeneLengths(sce, loc = "a"))
@@ -10,7 +29,6 @@ test_that("addGeneLengths generate method works", {
 })
 
 test_that("addGeneLength sample method works", {
-    sce <- simpleSimulate()
     lens <- round(runif(100, 100, 10000))
     expect_silent(addGeneLengths(sce, method = "sample", lengths = lens))
     expect_error(addGeneLengths(sce, method = "sample"))
diff --git a/tests/testthat/test-SimpleParams.R b/tests/testthat/test-SimpleParams.R
new file mode 100644
index 0000000000000000000000000000000000000000..3fa78dc650bded2279c5f6298882737dafff4a9c
--- /dev/null
+++ b/tests/testthat/test-SimpleParams.R
@@ -0,0 +1,7 @@
+context("SimpleParams")
+
+params <- newSimpleParams()
+
+test_that("printing works", {
+    expect_output(show(params), "A Params object of class SimpleParams")
+})
diff --git a/tests/testthat/test-SplatParams.R b/tests/testthat/test-SplatParams.R
index 208f0dfa24b672635f12709d4823b49cdaa3c7d7..91695dfdb193fb493c224e30b8e19f8a1a908d88 100644
--- a/tests/testthat/test-SplatParams.R
+++ b/tests/testthat/test-SplatParams.R
@@ -1,7 +1,12 @@
 context("SplatParams")
 
+params <- newSplatParams()
+
+test_that("printing works", {
+    expect_output(show(params), "A Params object of class SplatParams")
+})
+
 test_that("nBatches checks work", {
-  params <- newSplatParams()
   expect_error(setParam(params, "nCells", 1),
                "nCells cannot be set directly, set batchCells instead")
   expect_error(setParam(params, "nBatches", 1),
@@ -9,22 +14,20 @@ test_that("nBatches checks work", {
 })
 
 test_that("nGroups checks work", {
-    params <- newSplatParams()
     expect_error(setParam(params, "nGroups", 1),
                  "nGroups cannot be set directly, set group.prob instead")
 })
 
 test_that("path.from checks work", {
-    params <- newSplatParams()
-    params <- setParams(params, group.prob = c(0.5, 0.5))
-    params <- setParamUnchecked(params, "path.from", c(0, 1))
-    expect_silent(validObject(params))
-    params <- setParamUnchecked(params, "path.from", c(0, 3))
-    expect_error(validObject(params), "invalid class")
-    params <- setParamUnchecked(params, "path.from", c(1, 0))
-    expect_error(validObject(params), "path cannot begin at itself")
-    params <- newSplatParams()
-    params <- setParams(params, group.prob = c(0.3, 0.3, 0.4))
-    params <- setParamUnchecked(params, "path.from", c(2, 1, 1))
-    expect_error(validObject(params), "origin must be specified in path.from")
+    pp <- setParams(params, group.prob = c(0.5, 0.5))
+    pp <- setParamUnchecked(pp, "path.from", c(0, 1))
+    expect_silent(validObject(pp))
+    pp <- setParamUnchecked(pp, "path.from", c(0, 3))
+    expect_error(validObject(pp), "invalid class")
+    pp <- setParamUnchecked(pp, "path.from", c(1, 0))
+    expect_error(validObject(pp), "path cannot begin at itself")
+    pp <- newSplatParams()
+    pp <- setParams(pp, group.prob = c(0.3, 0.3, 0.4))
+    pp <- setParamUnchecked(pp, "path.from", c(2, 1, 1))
+    expect_error(validObject(pp), "origin must be specified in path.from")
 })
diff --git a/tests/testthat/test-ZINBParams.R b/tests/testthat/test-ZINBParams.R
index bbb7abd371aa1cddae7f7332201fe10bfc209f62..061bb8ae7675db988e532f112cdf24cf4dea822a 100644
--- a/tests/testthat/test-ZINBParams.R
+++ b/tests/testthat/test-ZINBParams.R
@@ -1,11 +1,16 @@
 context("ZINBParams")
 
+params <- newZINBParams()
+
 test_that("constructor is valid", {
-    expect_true(validObject(newZINBParams()))
+    expect_true(validObject(params))
+})
+
+test_that("printing works", {
+    expect_output(show(params), "A Params object of class ZINBParams")
 })
 
 test_that("nGenes checks work", {
-    params <- newZINBParams()
     expect_error(setParam(params, "nGenes", 1),
                  "nGenes cannot be set directly")
     expect_error(setParam(params, "nCells", 1),
diff --git a/tests/testthat/test-compare.R b/tests/testthat/test-compare.R
new file mode 100644
index 0000000000000000000000000000000000000000..04d652082f78507a9edfa5fa0da889c5f4d4e59b
--- /dev/null
+++ b/tests/testthat/test-compare.R
@@ -0,0 +1,59 @@
+context("Comparison functions")
+
+sim1 <- splatSimulate(nGenes = 1000, batchCells = 20)
+sim2 <- simpleSimulate(nGenes = 1000, nCells = 20)
+
+comparison <- compareSCEs(list(Splat = sim1, Simple = sim2))
+difference <- diffSCEs(list(Splat = sim1, Simple = sim2), ref = "Simple")
+
+test_that("compareSCEs works", {
+    expect_length(comparison, 3)
+    expect_true(all(c("FeatureData", "PhenoData", "Plots") %in%
+                        names(comparison)))
+    checkmate::expect_class(comparison$PhenoData, "data.frame")
+    checkmate::expect_class(comparison$FeatureData, "data.frame")
+    expect_length(comparison$Plots, 7)
+    expect_true(all(c("Means", "Variances", "MeanVar", "LibrarySizes",
+                      "ZerosGene", "ZerosCell", "MeanZeros") %in%
+                        names(comparison$Plots)))
+    for (plot in names(comparison$Plots)) {
+        checkmate::expect_class(comparison$Plots[[plot]], "ggplot")
+    }
+})
+
+test_that("diffSCEs works", {
+    expect_length(difference, 5)
+    expect_true(all(c("Reference", "FeatureData", "PhenoData", "Plots",
+                      "QQPlots") %in% names(difference)))
+    checkmate::expect_class(difference$Reference, "SingleCellExperiment")
+    checkmate::expect_class(difference$PhenoData, "data.frame")
+    checkmate::expect_class(difference$FeatureData, "data.frame")
+    expect_length(difference$Plots, 7)
+    expect_true(all(c("Means", "Variances", "MeanVar", "LibrarySizes",
+                      "ZerosGene", "ZerosCell", "MeanZeros") %in%
+                        names(difference$Plots)))
+    for (plot in names(difference$Plots)) {
+        checkmate::expect_class(difference$Plots[[plot]], "ggplot")
+    }
+    expect_length(difference$QQPlots, 5)
+    expect_true(all(c("Means", "Variances", "LibrarySizes", "ZerosGene",
+                      "ZerosCell") %in% names(difference$QQPlots)))
+    for (plot in names(difference$QQPlots)) {
+        checkmate::expect_class(difference$QQPlots[[plot]], "ggplot")
+    }
+})
+
+# test_that("makeCompPanel works", {
+#     panel <- makeCompPanel(comparison)
+#     checkmate::expect_class(panel, "ggplot")
+# })
+#
+# test_that("makeDiffPanel works", {
+#     panel <- makeDiffPanel(difference)
+#     checkmate::expect_class(panel, "ggplot")
+# })
+#
+# test_that("makeOverallPanel works", {
+#     panel <- makeOverallPanel(comparison, difference)
+#     checkmate::expect_class(panel, "ggplot")
+# })
diff --git a/tests/testthat/test-listSims.R b/tests/testthat/test-listSims.R
new file mode 100644
index 0000000000000000000000000000000000000000..cf386c9437a04bcb0898e6cf633fc9e47a8aeab1
--- /dev/null
+++ b/tests/testthat/test-listSims.R
@@ -0,0 +1,10 @@
+context("listSims")
+
+test_that("listSims printing works", {
+    expect_output(listSims(), "Splatter currently contains")
+})
+
+test_that("listSims return works", {
+    ll <- listSims(print = FALSE)
+    checkmate::expect_class(ll, "data.frame")
+})
diff --git a/tests/testthat/test-lunEstimate.R b/tests/testthat/test-lunEstimate.R
new file mode 100644
index 0000000000000000000000000000000000000000..010ae358c0b9a825902f30e7d791e91abf409a7e
--- /dev/null
+++ b/tests/testthat/test-lunEstimate.R
@@ -0,0 +1,9 @@
+context("lunEstimate")
+
+library(scater)
+data("sc_example_counts")
+
+test_that("lunEstimate works", {
+    params <- lunEstimate(sc_example_counts)
+    expect_true(validObject(params))
+})
diff --git a/tests/testthat/test-phenoEstimate.R b/tests/testthat/test-phenoEstimate.R
new file mode 100644
index 0000000000000000000000000000000000000000..402d78164c1ad0e9491097aaa3cc978ab015e44d
--- /dev/null
+++ b/tests/testthat/test-phenoEstimate.R
@@ -0,0 +1,9 @@
+context("phenoEstimate")
+
+library(scater)
+data("sc_example_counts")
+
+test_that("phenoEstimate works", {
+    params <- phenoEstimate(sc_example_counts)
+    expect_true(validObject(params))
+})
diff --git a/tests/testthat/test-simpleEstimate.R b/tests/testthat/test-simpleEstimate.R
new file mode 100644
index 0000000000000000000000000000000000000000..3b581e1e25d09f87b79959934edcf82b6f93883f
--- /dev/null
+++ b/tests/testthat/test-simpleEstimate.R
@@ -0,0 +1,9 @@
+context("simpleEstimate")
+
+library(scater)
+data("sc_example_counts")
+
+test_that("simpleEstimate works", {
+    params <- simpleEstimate(sc_example_counts)
+    expect_true(validObject(params))
+})
diff --git a/tests/testthat/test-splat-simulate.R b/tests/testthat/test-splat-simulate.R
index 9d99cf7b7fc3c762d7a821a255c9ae6415ea87ad..d5b16f588beaa9f0d96499222a19b18298b71ff4 100644
--- a/tests/testthat/test-splat-simulate.R
+++ b/tests/testthat/test-splat-simulate.R
@@ -4,9 +4,11 @@ test.params <- newSplatParams(nGenes = 100, batchCells = c(5, 5),
                               group.prob = c(0.5, 0.5), lib.scale = 0)
 
 test_that("splatSimulate output is valid", {
-    expect_true(validObject(splatSimulate(test.params, method = "single")))
+    expect_true(validObject(splatSimulate(test.params, method = "single",
+                                          dropout.present = TRUE)))
     expect_true(validObject(splatSimulate(test.params, method = "groups")))
-    expect_true(validObject(splatSimulate(test.params, method = "paths")))
+    expect_true(validObject(splatSimulate(test.params, method = "paths",
+                                          path.from = c(0, 1))))
 })
 
 test_that("one group switches to single mode", {
diff --git a/tests/testthat/test-utils.R b/tests/testthat/test-utils.R
new file mode 100644
index 0000000000000000000000000000000000000000..d4b7bdc9c180b44f901f5fcc17435e83755df90d
--- /dev/null
+++ b/tests/testthat/test-utils.R
@@ -0,0 +1,22 @@
+context("utils")
+
+test_that("logistic function works", {
+    expect_equal(logistic(0, x0 = 0, k = 1), 0.5)
+})
+
+test_that("rbindMatched works", {
+    df1 <- data.frame(A = 1:3, B = 4:6, C = 7:9)
+    df2 <- data.frame(D = 0)
+    expect_error(rbindMatched(df1, df2),
+                 "There must be at least two columns in common")
+    df2 <- data.frame(A = 1:3)
+    expect_error(rbindMatched(df1, df2),
+                 "There must be at least two columns in common")
+    df2 <- data.frame(A = 1:3, C = 7:9, D = 0)
+    expect_equal(colnames(rbindMatched(df1, df2)), c("A", "C"))
+})
+
+test_that("winsorize works", {
+    x <- c(0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2)
+    expect_true(all(winsorize(x, q = 0.1) == 1))
+})