Welcome!
This site contains the materials for the R/Pharma workshop titled, Developing & Testing Your Shiny Application.
Workshop Description
This talk takes a deep dive into the world of testing shiny applications, covering strategies for determining what needs to be tested to ensure your app’s functional accuracy and reliability. Shiny’s reactive programming model requires specialized approaches to testing, distinct from traditional R package testing.
I’ll begin by describing the application of unit, integration, and end-to-end testing in Shiny apps. Then we’ll move into the role of testing in development and highlight the need for code organization when designing your testing suite.
The focus then shifts to practical aspects of testing by illustrating tools like test data and fixtures. Attendees will see example tests for utility functions, modules, and tests to capture specific user interactions (and confirm the application behaves as expected).
Finally, I will demonstrate advanced topics like test coverage, what it measures, and why 100% coverage isn’t necessarily a metric worth chasing.
This presentation will give R developers a toolkit of testing techniques (building a test suite, writing effective tests, and automated testing) regardless of their familiarity with Shiny.
Workshop Topic Index
Below is an index for each topic, slide, and chapter in Shiny App-Packages. The quickest way to access each branch/app is with the shinypak
package.
# install.packages("pak")
::pak("mjfrigaard/shinypak")
paklibrary(shinypak)
List all the apps with list_apps()
head(list_apps())
#> branch last_updated
#> 2 01_whole-app-game 2024-01-01 14:11:32
#> 1 02.1_shiny-app 2024-01-04 13:05:58
#> 4 02.2_movies-app 2024-01-04 13:07:59
#> 5 02.3_proj-app 2024-01-04 13:08:58
#> 6 03.1_description 2024-01-04 13:10:00
#> 7 03.2_rproj 2024-01-04 13:25:06
Launch an app with launch()
launch(app = "02.3_proj-app")
Shiny Apps and R packages
Topic |
Video/Slide/Branch |
Book section |
Basic Shiny Apps | 6:15 / 5 /02.1_shiny-app |
Shiny Apps covers creating a new Shiny app in Posit Workbench and the boilerplate code. |
Advanced Shiny Apps | 8:37 / 7 / 02.2_movies-app , 02.3_proj-app |
The code for our application is introduced in Movie review data app, and the utility function, modules, and data are covered in Project folders |
Rproj fields |
13:38 / 14 / 03.2_rproj |
R Projects discusses what’s in the .Rproj file (and project vs. package fields). |
Transitioning to a Package | 20:18 / 15 / 03.1_description , 03.3_create-package |
Creating app-packages covers converting and creating app-packages with usethis::create_package() |
DESCRIPTION fields |
25:51 / 16 / 03.3_create-package |
Storing/supplying your personal information in new packages is discussed in DESCRIPTION arguments |
Load, document, and install | 28:01 / 18 / 04_devtools |
Building R packages means adopting new package development habits |
The benefits of document() |
31:26 / 20 / 04_devtools |
Documentation covers the multiple outputs created with devtools::document() |
Running check() |
35:14 / 23 / 04_devtools |
How often/should you run Check? |
R Package Contents
Topic |
Video/Slide/Branch |
Book section |
Documentation | 41:39 / 26 / 05_roxygen2 |
Learn the basics of function documentation with roxygen2 basics |
Help files | 45:03 / 27 / 05_roxygen2 |
Preview help files while documenting app functions |
Dependencies | 47:21 / 28 / 06.1_pkg-exports |
Introduction to managing dependencies |
Exports | 49:44 / 29 / 06.1_pkg-exports |
Exports from your app-package |
Imports | 53:01 / 30 / 06.2_pkg-imports |
Imports into your app-package |
Data | 1:03:15 / 33 / 07_data |
Storing, loading, and documenting data |
Accessing files with system.file() |
1:08:51 / 37 / 07_data |
How to use the inst/extdata folder |
App-Package Contents
Topic |
Video/Slide/Branch |
Book section |
Launching apps | 1:21:17 / 40 / 08_launch-app |
Launch covers Shiny’s three functions for running apps (shinyApp() , runApp() , and shinyAppDir() ) |
Standalone app functions | 1:22:07 / 41 / 08_launch-app |
Standalone options provides some methods/approaches to writing the primary function to run your application. |
app.R files |
1:27:07 / 44 / 08_launch-app |
app.R options includes packages and functions to consider including in the root app.R file (and how to use it non-interactively). |
External resources | 1:30:32 / 45 / 09.1_inst-www |
Most Shiny apps require some external files–this chapter covers how to include them. |
addResourcePath() and system.file() |
1:31:12 / 46 / 09.1_inst-www , 09.2_inst-bslib |
The differences between the ‘source’ and ‘installed’ package is covered in package files, and including alternative image files/UI arguments is discussed in bslib layout |
‘development’ vs ‘production’ directories | 1:43:41 / 48 / 09.3_inst-dev , 09.4_inst-prod |
This chapter also covers how to use inst/ to store dev data and production (prod ) versions of your app |
Questions from chat
Am I planning on contrasting this package development approach with a [Shiny] framework?
- Brief discussion of the
golem
framework: 1:51:09
- Brief discussion of the
Choosing one framework over another in terms of design and how to best prepare your app as it becomes more complicated or how you choose the best way to ‘future proof’ your app?
- My rather lengthy non-answer starts at 1:54:14
The order of learning when it comes to our Shiny versus R packages (like learning before the other)
- Shameless plug for my Shiny App-Packages book starting at: 1:56:15
Tests
Topic |
Video/Slide/Branch |
Book section |
Tests | 2:00:45 / 51 / 11_tests-specs |
Tests gives an overview of the testing section (and links to additional resources) |
Test suite | 2:02:15/ 52 / 11_tests-specs |
Test suite covers how to setup your testthat tests, creating new tests, running tests interactively, etc. |
App specifications | 2:09:46/ 56 / 11_tests-specs |
Specifications compares user specifications, features, and functional requirements (or how to figure out what to test) |
Connecting user specifications and tests | 2:11:40 / 57 / 11_tests-specs |
The traceability matrix section gives an example of a user specification mapped to a feature linked to a functional requirement connected to a test. |
testthat BDD functions |
2:18:25 / 59 / 11_tests-specs |
BDD and testthat covers using describe() and it() with the Gherkin syntax |
Test fixtures | 2:22:07 / 61 / 12.1_tests-fixtures |
The fixtures section uses the same (data) example fixture, but gives more information on using them in tests. |
Test helpers | 2:32:09 / 66 / 12.2_tests-helpers |
Test helpers covers some dos and don’ts of writing test helpers (it’s OK if test code doesn’t 100% adhere to the DRY principle) |
Testing modules | 2:37:59 / 72 / 13_tests-modules |
Integration tests discusses testing module server functions with testServer() |
System tests | 2:48:54 / 82 / 14_tests-system |
System tests covers setting up shinytest2 , recording and writing tests. |
About Me
Martin Frigaard is a Shiny Developer and tidyverse
instructor. Find him on LinkedIn.