Можно ли использовать данные пакета R в testthat tests или run_examples ()?

Я работаю над разработкой пакета R, используя devtools, testthat и roxygen2. У меня есть пара наборов данных в папке данных (foo.txt и bar.csv).

Моя файловая структура выглядит так:

/ mypackage
    / data
        * foo.txt, bar.csv
    / inst
        / tests
            * run-all.R, test_1.R
    / man
    / R

Я почти уверен, что 'foo' и 'bar' задокументированы правильно:

    #' Foo data
    #'
    #' Sample foo data
    #'
    #' @name foo
    #' @docType data
    NULL
    #' Bar data
    #'
    #' Sample bar data
    #'
    #' @name bar
    #' @docType data
    NULL

Я хотел бы использовать данные из 'foo' и 'bar' в моих примерах документации и модульных тестах.

Например, я хотел бы использовать эти наборы данных в своих тестах testthat, вызвав:

    data(foo)
    data(bar)
    expect_that(foo$col[1], equals(bar$col[1]))

И я бы хотел, чтобы примеры в документации выглядели так:

    #' @examples
    #' data(foo)
    #' functionThatUsesFoo(foo)

Если я пытаюсь вызвать data (foo) во время разработки пакета, я получаю сообщение об ошибке «data set 'foo' not found». Однако, если я соберу пакет, установлю его и загрузю - тогда я смогу заставить тесты и примеры работать.

Мои текущие обходные пути - не запускать пример:

    #' @examples
    #' \dontrun{data(foo)}
    #' \dontrun{functionThatUsesFoo(foo)}

И в тестах предварительно загружайте данные, используя путь, специфичный для моего локального компьютера:

    foo <- read.delim(pathToFoo, sep="\t", fill = TRUE, comment.char="#")
    bar <- read.delim(pathToBar, sep=";", fill = TRUE, comment.char="#"
    expect_that(foo$col[1], equals(bar$col[1]))

Это не кажется идеальным - особенно с учетом того, что я сотрудничаю с другими - требуя, чтобы у всех соавторов были одинаковые полные пути к 'foo' и 'bar'. Кроме того, примеры в документации выглядят так, как будто их невозможно запустить, хотя после установки пакета они могут.

Какие-либо предложения? Большое спасибо.


person ldecicco    schedule 17.01.2012    source источник
comment
Не используйте data (). Просто положитесь на ленивую загрузку.   -  person hadley    schedule 20.01.2012
comment
Извините за последний комментарий, я все еще привыкаю к ​​этому форматированию. Спасибо @hadley. Это помогло с тестом. Я все еще не понимаю, как сделать пример в документации (используя roxygen2), который позволяет мне воспользоваться набором данных.   -  person ldecicco    schedule 24.01.2012
comment
Если вы конвертируете данные в .Rdata файлы, load_all загрузит их за вас.   -  person hadley    schedule 24.01.2012


Ответы (2)


Импорт файлов, не относящихся к RData, в примерах / тестах

Я нашел решение этой проблемы, заглянув в пакет JSONIO , который, очевидно, должен был предоставить некоторые примеры чтения файлов, отличных от файлов .RData.

Я заставил это работать в примерах на уровне функций и удовлетворять как R CMD check mypackage, так и testthat::test_package().

(1) Измените структуру вашего пакета так, чтобы каталог данных примера находился внутри inst. В какой-то момент R CMD check mypackage сказал мне переместить файлы данных, не относящиеся к RData, в inst/extdata, поэтому в этой новой структуре он также переименован.

/ mypackage
    / inst
        / tests
            * run-all.R, test_1.R
        / extdata
            * foo.txt, bar.csv
    / man
    / R
    / tests
        * run-testthat-mypackage.R

(2) (Необязательно) Добавьте каталог верхнего уровня tests, чтобы ваш новый тест теперь также запускался во время R CMD check mypackage.

В сценарии run-testthat-mypackage.R должны быть как минимум две следующие строки:

library("testthat")
test_package("mypackage")

Обратите внимание, что это та часть, которая позволяет вызывать test во время R CMD check mypackage, и в противном случае не требуется. Вы также должны добавить testthat в качестве зависимости «Предлагает:» в свой файл DESCRIPTION.

(3) Наконец, секретный соус для указания пути внутри пакета:

barfile <- system.file("extdata", "bar.csv", package="mypackage")
bar <- read.csv(barfile)
# remainder of example/test code here...

Если вы посмотрите на вывод команды system.file(), она возвращает полный системный путь к вашему пакету в рамках R. В Mac OS X это выглядит примерно так:

"/Library/Frameworks/R.framework/Versions/2.15/Resources/library/mypackage/extdata/bar.csv"

Причина, по которой мне это кажется нормальным, заключается в том, что вы не кодируете жестко какие-либо функции пути, кроме тех, что находятся в вашем пакете, поэтому этот подход должен быть надежным по сравнению с другими установками R в других системах.

data() подход

Что касается семантики data(), насколько я могу судить, она характерна для двоичных файлов R (.RData) в каталоге data верхнего уровня. Таким образом, вы можете обойти мой пример выше, предварительно импортировав файлы данных и сохранив их с помощью команды save() в свой каталог данных. Однако это предполагает, что вам нужно только показать пример, в котором данные уже загружены в R, в отличие от воспроизводимой демонстрации восходящего процесса импорта файлов.

person Paul McMurdie    schedule 21.06.2012
comment
Спасибо за подробный ответ! - person ldecicco; 25.07.2012
comment
Пожалуйста. Я рад, что это помогло. Это стало полезным для разработки моего собственного пакета, поэтому я хотел поделиться. - person Paul McMurdie; 01.08.2012
comment
Я пытался понять, как сделать воспроизводимым и восходящий процесс импорта. Типичный случай использования, который у меня есть, - это то, что я хочу работать с нетривиальным преобразованием некоторых шейп-файлов - возможно, это займет минуту или около того. Я могу включить шейп-файлы в inst/extdata, но мне никогда не удается найти этот путь из кода, выполняющегося внутри install(). Кроме того, даже document(), похоже, хочет восстановить все .r файлы внутри data/. Я не хочу перестраивать их каждый раз, когда добавляю или изменяю документацию для функции. data/Makefile, но это кажется глупым. Полезные советы! - person dholstius; 24.09.2013
comment
@holstius Почему у вас .r файлы внутри data/? Ваши тесты восстановления данных должны запускаться кодом модульного тестирования в tests или inst/tests. Если расследование этого не помогает, я предлагаю создать отдельный вопрос SO для вашего комментария с чем-то, что приближается к воспроизводимому примеру. - person Paul McMurdie; 02.10.2013

Согласно комментарию @hadley, преобразование .RData будет работать хорошо.

Что касается более широкого вопроса о коллективном сотрудничестве с различными средами между членами команды, общий шаблон состоит в том, чтобы согласовать одну переменную среды, например FOO_PROJECT_ROOT, которую каждый в команде будет соответствующим образом настроить в своей среде. С этого момента вы можете использовать относительные пути, в том числе между проектами.

Подход, специфичный для R, заключался бы в согласовании некоторых данных / функций, которые каждый член команды будет настраивать в своих .Rprofile файлах. Так, например, devtools находит пакеты в нестандартных местах.

И последнее, но не менее важное: хотя это не оптимально, вы можете поместить код, специфичный для разработчика, в свой репозиторий. Если @hadley это сделает, это не так уж и плохо. Посмотрите, например, как он активирует определенные действия в testthat в его собственное окружение.

person Sim    schedule 20.06.2012