| 1 | # Core function to execute R unit tests (or just show functions names) |
| 2 | .pkgdev.rtest = function(path, prefix, show, cc) { |
| 3 | |
| 4 | # Initial step: list every potential unit test under path/R/tests. |
| 5 | allFuncNames = .parseRunitTests(file.path(path,"R","tests")) |
| 6 | |
| 7 | # Filter functions names matching prefix |
| 8 | funcNames = grep( paste("^test_",prefix,sep=''), allFuncNames, value=TRUE ) |
| 9 | if (length(funcNames) == 0) return #shortcut: nothing to do... |
| 10 | |
| 11 | # If show==TRUE, display every potential test starting with prefix, and exit |
| 12 | if (show) { |
| 13 | #display in alphabetic order |
| 14 | return (paste(sort(funcNames), sep='\n')) |
| 15 | } |
| 16 | |
| 17 | # Source all R unit test files |
| 18 | rFiles = list.files(file.path(path,"R","tests"), |
| 19 | pattern="\\.[RrSsq]$", full.names=TRUE, recursive=TRUE) |
| 20 | lapply(rFiles, source) |
| 21 | |
| 22 | # Source R file containing unit tests methods |
| 23 | pkdev_path = file.path(Sys.getenv("R_HOME_USER"), "pkgdev") |
| 24 | source(file.path(pkdev_path,"R","tests","unitTestsMethods.R")) |
| 25 | |
| 26 | # Get package name from path |
| 27 | pathTokens = strsplit(path, c(.Platform$file.sep))[[1]] |
| 28 | pkgName = pathTokens[length(pathTokens)] |
| 29 | |
| 30 | # This file tells if the package is currently loaded |
| 31 | pkgLoadFile = file.path(pkdev_path,"pkgs",pkgName,"loaded") |
| 32 | |
| 33 | # Now manually load package (may not be installable if non-flat) |
| 34 | pkgAlreadyLoaded = file.exists(pkgLoadFile) |
| 35 | .pkgdev.load(path, cc) |
| 36 | |
| 37 | # Run selected tests (after 'funcs' filter applied) |
| 38 | for (funcName in funcNames) { |
| 39 | cat(">>> Running ",funcName,"\n",sep='') |
| 40 | func = match.fun(funcName) |
| 41 | execTime = as.numeric(system.time(func())[1]) |
| 42 | cat(">>> ... completed in ",execTime,"s.\n",sep='') |
| 43 | } |
| 44 | |
| 45 | # Unload shared library if it wasn't already loaded |
| 46 | if (!pkgAlreadyLoaded) .pkgdev.unload(path) |
| 47 | } |
| 48 | |
| 49 | # Recursively explore initial path to parse source files for unit tests. |
| 50 | .parseRunitTests = function(path) { |
| 51 | |
| 52 | # Unit test names to return |
| 53 | funcNames = c() |
| 54 | |
| 55 | # For each file in current folder |
| 56 | for (fileName in list.files(path, full.names=TRUE, recursive=TRUE)) { |
| 57 | |
| 58 | # If the file is not a source, skip |
| 59 | if ( length( grep("\\.[RrSsq]$", fileName) ) == 0) next |
| 60 | |
| 61 | # Every test function has a name starting with "test_" |
| 62 | matches = grep( |
| 63 | "^[ \t]*test_[a-zA-Z0-9_]*[ \t]*(=|<-)[ \t]*function.*", |
| 64 | scan(fileName, what="character", sep='\n', quiet=TRUE), |
| 65 | value = TRUE) |
| 66 | |
| 67 | # We matched more to be 100% sure we got test functions, but need to strip now |
| 68 | funcNames = c(funcNames, sub( |
| 69 | "^[ \t]*(test_[a-zA-Z0-9_]*)[ \t]*(=|<-)[ \t]*function.*", |
| 70 | "\\1", |
| 71 | matches)) |
| 72 | } |
| 73 | |
| 74 | return (funcNames) |
| 75 | } |