Creating local functions in testthat files gives RCMD check error

Am creating a package for testing the asymptotic complexity of different algorithms in R and am currently creating testthat files for specific use-cases, (such as sorting algorithms, machine algorithm algorithms, changepoint detection algorithms etcetera) wherein I am using some local non-imported functions in the testthat files, such as for example a sort function, and testing for the same inside the scope of the second parameter for a test_that call, which results in a test fail:

could not find function "merge.sort"
Backtrace:
 1. testComplexity::asymptoticTimings(...)
 4. testComplexity:::fun.obj(data.sizes[i])

[1] "loglinear"
[1] "loglinear"
[1] "loglinear"
[1] "loglinear"
== testthat results  ==================================================================================================
[ OK: 30 | SKIPPED: 0 | WARNINGS: 802 | FAILED: 1 ]
2. Error: Merge sort test (@test-testsforsortingalgorithms.R#44) 

Error: testthat unit tests failed
In addition: Warning message:
package 'testthat' was built under R version 3.6.3 
Execution halted

for the testthat file test-testsforsortingalgorithms (not committed to development branch in github since it produces error):

library(testthat)

test_that("Shell sort test", {
  df <- asymptoticTimings(sort(sample(1:100, data.sizes, replace = TRUE), method = "shell" , index.return = TRUE), data.sizes = 10^seq(1, 3, by = 0.5))
  expect_equal(asymptoticTimeComplexityClass(df), "loglinear")
})

test_that("Radix sort test", {
  df <- asymptoticTimings(sort(sample(1:100, data.sizes, replace = TRUE), method = "radix" , index.return = TRUE), data.sizes = 10^seq(1, 3, by = 0.5))
  expect_equal(asymptoticTimeComplexityClass(df), "loglinear")
})

test_that("Merge sort test", {
  merge <-function(a,b)
  {
    r <-numeric(length(a)+length(b))
    ai<-1; bi<-1; j<-1;
    for(j in 1:length(r))
    {
      if((ai<=length(a) && a[ai]<b[bi]) || bi>length(b))
      {
        r[j] <- a[ai]
        ai <- ai+1
      } else
      {
        r[j] <- b[bi]
        bi <- bi+1
      }
    }
    return(r)
  }
  merge.sort<-function(A)
  {
    if(length(A)>1)
    { q <- ceiling(length(A)/2)
    a <- merge.sort(A[1:q])
    b <- merge.sort(A[(q+1):length(A)])
    merge(a,b)
    } else return(A)
  }
  df <- asymptoticTimings(merge.sort(sample(1:100, data.sizes, replace = TRUE)), data.sizes = 10^seq(1, 3, by = 0.5))
  expect_equal(asymptoticTimeComplexityClass(df), "loglinear")
})

For reproducibility, please try the following steps:

  • Install the package via devtools/remote:
devtools::install_github("Anirban166/testComplexity")
remotes::install_github("Anirban166/testComplexity")
  • Create any testthat file within tests > testthat >, and copy paste any of the test cases below, all of which create a function within the testthat file (non-imported, and local to file scope):
# test case 1:
test_that("Dummy function test", {
  dummyfunc <- function(N)
  {
    return(rpois(N, 10))
  }
  df <- asymptoticTimings(dummyfunc(data.sizes), data.sizes = 10^seq(1, 3, by = 0.5))
  expect_true(asymptoticTimeComplexityClass(df) %in% c("constant", "log", "linear", "loglinear", "quadratic"))
})

# test case 2:
test_that("Bubble sort test", {
  bubble.sort <- function(x)
  { n <- length(x)
  for(i in 1:(n-1))
  {
    for(j in 1:(n-i))
    {
      if(x[j+1] < x[j])
      {   tmp <- x [j]
      x[j] <- x[j+1]
      x[j+1] <- tmp
      }
    }
  }
  return(x)
  }
  df <- asymptoticTimings(bubble.sort(sample(1:100, data.sizes, replace = TRUE)), data.sizes = 10^seq(1, 3, by = 0.5))
  expect_true(asymptoticTimeComplexityClass(df) %in% c("constant", "log", "linear", "loglinear", "quadratic"))
})

# test case 3
test_that("Selection sort test", {
  selection.sort <- function(x)
  {   max <- length(x)
  for (j in 1:(max-1))
  {
    m <- x[j]
    p <- j
    for(k in (j+1):max)
    {
      if(x[k] < m)
        m <- x[k]
      p <- k
    }
    x[p] <- x[j]
    x[j] <- m
  }
  return(x)
  }
  df <- asymptoticTimings(selection.sort(sample(1:100, data.sizes, replace = TRUE)), data.sizes = 10^seq(1, 3, by = 0.5))
  expect_equal(asymptoticTimeComplexityClass(df), "quadratic")
})
  • Save the file and run an RCMD check() to reproduce the error

Do note that this is not a testthat problem, but since am receiving an RCMD check error for testthat cases, and in particular for locally created functions only (it gives no error for imported functions from packages, or generally available functions such as the sort() function, which I used above in my code with no error), I went with the given title and appended tags.

Another thing to note is that the user-provided algorithm should be a function of the data.sizes parameter, since the function operates internally on some data size, say N for algorithm(N) (with larger data sizes on a scale of powers of ten being preferred) if you want to create test cases apart from the ones given above (or simply mention me!)

Also, Gabor Csardi pointed out the fact that am not evaluating data.sizes in the right environment, so I want to know how can I construct the right evaluation environment for this? (this is my function in which data.sizes is evaluated) would be very grateful if anybody can help me resolve this!

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.