Comment déboguer son package sur Win-Builder avant d'envoyer vers le CRAN ?

Soumettre un package au CRAN peut être difficile car il est vérifié sur plusieurs systèmes d’exploitation et versions de R que vous n’êtes peut-être pas en mesure de vérifier vous-même localement. Heureusement, certains services comme {rhub} et Win-Builder évitent certaines erreurs CRAN malencontreuses. Mais comment déboguer du code qui est exécuté sur un serveur externe, sans y avoir accès directement, comme Win-Builder ? Utilisez la puissance des tests unitaires…

Pas l’temps de tout lire…

Pour déboguer votre code sur Win-Builder, vous pouvez créer des tests unitaires qui sauvegardent certaines sorties dans le dossier “testthat/”. Sauvegardez toutes les sorties significatives et intermédiaires que vous voudrez ouvrir ou exécuter localement après le téléchargement. Compressez ces fichiers dans un fichier zip en utilisant utils::zip() dans ce même répertoire. Ensuite, sur la page Win-Builder dédiée à votre package, vous pourrez le télécharger et l’explorer localement.

Notez que certains formats de fichiers ne sont pas téléchargeables depuis le serveur, c’est pourquoi je recommande un fichier zip.

Enregistrer des fichiers dans le répertoire “testthat/” est une pratique à éviter pour une soumission. Vous êtes censés laisser les lieux propres après avoir quitté les tests. Cependant, ici, vous le faites pour le débogage. Par ailleurs, si vous voulez garder le code de débogage pour une utilisation future, mais laisser l’état propre une fois que tout est mis en place pour le CRAN, utilisez un paramètre dans vos tests.
Par exemple, voici une partie de mon code de test unitaires pour {gitdown} :

# debug if problems with CRAN to retrieve outputs
debug <- FALSE

repo_input <- tempfile(pattern = "git2r-")
repo <- fake_repo(repo_input)

# Classic use
with_dir(repo, {
  res <- git_down(author = "Cervan",
                  pattern = c("Issue" = "#[[:digit:]]+"),
                  open = FALSE
  )
})

test_that("git_down function",{
  expect_match(res, regexp = ".html")
  expect_true(file.exists(file.path(dirname(res), "section-issue.html")))
})

# clean dir
if (debug) {
  dir.create("res_one")
  file.copy(dirname(res), "res_one", recursive = TRUE, overwrite = TRUE)
  # Zip it for download
  utils::zip(zipfile = "res_one.zip", files = "res_one")
}

Vous n’êtes pas vraiment prêt pour la soumission au CRAN, jusqu’à ce que vous le soyez…

J’ai décidé de soumettre au CRAN {gitdown}, un package qui crée un rapport bookdown des messages de commit ordonnés selon un motif. Je pensais qu’il était prêt à partir :

  • Il y a des exemples reproductibles pour chaque fonction exportée.
  • La couverture du code est élevée, ce qui évitera de nombreuses erreurs pour la maintenance future :
  • Les ‘checks’ passent localement
  • Les ‘checks’ passent sur les GitHub Actions pour chaque OS :
  • Sans compter qu’il y a aussi de la documentation avec les vignettes et du Readme. Elle n’est pas obligatoire pour le CRAN, mais elle est nécessaire si vous voulez que les gens puissent utiliser votre package.

J’ai suivi toutes les étapes du guide ThinkR : “Préparer son package pour une soumission au CRAN (EN)”. Cela inclut les vérifications avec {rhub}, un package qui permet de vérifier les packages sur plusieurs plateformes (récentes, anciennes, bizarres), en utilisant rhub::check_for_cran().

Nous voici donc maintenant à la dernière étape de vérification : Win-builder. C’est un service fourni par Uwe Ligges (mainteneur CRAN pour les package binaires Windows), qui est “destiné aux utilisateurs qui ne disposent pas de Windows, pour vérifier et construire les packages binaires Windows”. C’est un bon avant-goût des vérifications qui auront lieu sur les serveurs CRAN car toutes les vérifications ne sont pas incluses dans la fonction automatisée rcmdcheck::rcmdcheck(args = "--as-cran"). C’est là qu’arrivent mes problèmes.

Sur cette plateforme Windows spécifique, l’un de mes tests unitaires a échoué et je n’ai pas pu le reproduire, ni sur mon installation locale Windows, ni sur les deux configurations Windows sur les GitHub Actions : {os : windows-latest, r : 'release'} et {os : windows-latest, r : 'devel'}. La sortie d’une de mes fonctions était différente pour cette plateforme spécifique.

Je n’étais pas prêt à soumettre au CRAN…

Utiliser les fichiers de log pour tester localement les sorties distantes

Sur le serveur Win-Builder, vous pouvez obtenir le journal des vérifications et quelques autres fichiers.

Comme vous le feriez localement, vous examinez les checks. Cela permet de retrouver l’origine de l’erreur et de pouvoir ensuite en deviner la source.
Dans mon cas, un test unitaire a échoué. Il s’agit de tricoter (knit) un fichier Rmarkdown en HTML, mais le test dit que le fichier HTML de sortie n’existe pas.

Peut-être que mes tests n’étaient pas assez verbeux. Je pourrais peut-être faire d’autres tests. Mais comment puis-je obtenir le fichier Rmd qui n’a pas pu être tricoté correctement ?

Avec Win-Builder, vous n’obtenez pas seulement le fichier journal des check, vous pouvez récupérer des exemples de code et de sorties, ainsi que le contenu du répertoire “tests/” après avoir exécuté les vérifications, si vous cliquez sur “examples_and_tests” ci-dessus.
J’ai utilisé cette possibilité pour ajouter du code à l’intérieur de mes tests unitaires de façon à récupérer toutes les étapes intermédiaires et les fichiers dont j’avais besoin pour essayer de déboguer localement.

Tous les fichiers ne sont pas lisibles et téléchargeables sur Win-builder

Je me suis intéressé au fichier Rmd qui a conduit à l’échec de la compilation HTML. Cependant, certaines extensions de fichiers ne sont pas lisibles sur le serveur, ni téléchargeables.

Vous pouvez lire et télécharger :

  • “.R”
  • “.txt”
  • “.html”
  • “.zip”
  • “.css”
  • “.js”

Vous ne pouvez pas lire ni télécharger :

  • “.Rmd”
  • “.rds”
  • “.yml”

Il est donc préférable de compresser tout ce dont vous avez besoin dans un fichier zip, comme les objets R intermédiaires et les fichiers. Vous pourrez alors les télécharger et les explorer localement.

Pensez à créer ces parties de codes sous condition de telle sorte que tous ces fichiers utiles au débogage ne soient pas créés lorsque vous aurez tout réglé pour l’envoi au CRAN. Par exemple, voici une partie de mon code de test unitaire pour {gitdown} avec la condition pour le débogage :

# debug if problems with CRAN to retrieve outputs
debug <- FALSE

repo_input <- tempfile(pattern = "git2r-")
repo <- fake_repo(repo_input)

# Classic use
with_dir(repo, {
  res <- git_down(author = "Cervan",
                  pattern = c("Issue" = "#[[:digit:]]+"),
                  open = FALSE
  )
})

test_that("git_down function",{
  expect_match(res, regexp = ".html")
  expect_true(file.exists(file.path(dirname(res), "section-issue.html")))
})

# clean dir
if (debug) {
  dir.create("res_one")
  file.copy(dirname(res), "res_one", recursive = TRUE, overwrite = TRUE)
  # Zip it for download
  utils::zip(zipfile = "res_one.zip", files = "res_one")
}

Qu’en est-il de mon erreur rmarkdown, pandoc et knit sur Win-builder ?

Eh bien, il semble qu’une version potentiellement différente de pandoc n’était pas capable de séparer le texte du code inclus dans les backticks…

Voici la différence de code markdown, tel que vu par git, entre avant et après modification :

Voici la sortie HTML avant la modification du code markdown. Vous pouvez voir que les backticks après Message content: ne sont pas utilisés pour commencer un chunk de code.

Et après la modification, avec une ligne vide supplémentaire, le bloc de code après Message content: est bon.

Continuez à partager votre travail, c’est pour le bien de tous.

J’espère que cet article de blog pourra aider d’autres développeurs de packages R à réduire leur peine lorsqu’ils ou elles rendent leurs merveilleux packages disponibles à tous !

Notez que j’ai pu détecter mon problème uniquement grâce aux tests unitaires que j’ai mis dans le package. Ces tests garantissent que les sorties sont les mêmes quelles que soient les versions de l’OS, de R et des packages utilisés. Ne minimisez pas le pouvoir des tests unitaires.

Rappelez-vous qu’il existe un guide ThinkR avec toutes les étapes “Prepare your package for a CRAN submission”. Aussi, {usethis}, {devtools} et {rhub} sont vos amis sur ce chemin avant l’étape finale : devtools::release().



Citation :

Merci de citer ce travail avec :
Rochette Sébastien. (2021, avr.. 11). "Comment déboguer son package sur Win-Builder avant d'envoyer vers le CRAN ?". Retrieved from https://statnmap.com/fr/2021-04-11-comment-deboguer-son-package-sur-win-builder-avant-d-envoyer-vers-le-cran/.


Citation BibTex :
@misc{Roche2021Comme,
    author = {Rochette Sébastien},
    title = {Comment déboguer son package sur Win-Builder avant d'envoyer vers le CRAN ?},
    url = {https://statnmap.com/fr/2021-04-11-comment-deboguer-son-package-sur-win-builder-avant-d-envoyer-vers-le-cran/},
    year = {2021}
  }