test-shiny-app
О программе
Этот навык помогает разработчикам тестировать приложения Shiny с использованием shinytest2 для сквозного тестирования в браузере и testServer() для модульного тестирования серверной логики. Он охватывает снапшот-тестирование, интеграцию с CI и мокирование внешних сервисов. Используйте его при добавлении тестов к существующим приложениям, настройке тестирования для новых проектов, написании регрессионных тестов или интеграции тестов в CI/CD-пайплайны.
Быстрая установка
Claude Code
Рекомендуетсяnpx skills add pjt222/agent-almanac -a claude-code/plugin add https://github.com/pjt222/agent-almanacgit clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/test-shiny-appСкопируйте и вставьте эту команду в Claude Code для установки этого навыка
Документация
Test Shiny App
Set up comprehensive testing for Shiny applications using shinytest2 (end-to-end) and testServer() (unit tests).
When Use
- Add tests to existing Shiny application
- Set up testing strategy for new Shiny project
- Write regression tests before refactoring Shiny code
- Integrate Shiny app tests into CI/CD pipelines
Inputs
- Required: Path to Shiny application
- Required: Test scope (unit tests, end-to-end, or both)
- Optional: Whether to use snapshot testing (default: yes for e2e)
- Optional: CI platform (GitHub Actions, GitLab CI)
- Optional: Modules to test in isolation
Steps
Step 1: Install Testing Dependencies
install.packages("shinytest2")
# For golem apps, add as a Suggests dependency
usethis::use_package("shinytest2", type = "Suggests")
# Set up testthat infrastructure if not present
usethis::use_testthat(edition = 3)
Got: shinytest2 installed, testthat directory structure in place.
If fail: shinytest2 needs chromote (headless Chrome). Install Chrome/Chromium on system. WSL: sudo apt install -y chromium-browser. Verify with chromote::find_chrome().
Step 2: Write testServer() Unit Tests for Modules
Create tests/testthat/test-mod_dashboard.R:
test_that("dashboard module filters data correctly", {
testServer(dataFilterServer, args = list(
data = reactive(iris),
columns = c("Species", "Sepal.Length")
), {
# Set inputs
session$setInputs(column = "Species")
session$setInputs(value_select = "setosa")
session$setInputs(apply = 1)
# Check output
result <- filtered()
expect_equal(nrow(result), 50)
expect_true(all(result$Species == "setosa"))
})
})
test_that("dashboard module handles empty data", {
testServer(dataFilterServer, args = list(
data = reactive(iris[0, ]),
columns = c("Species")
), {
# Module should not error on empty data
expect_no_error(session$setInputs(column = "Species"))
})
})
Key patterns:
testServer()tests module server logic without a browser- Pass reactive arguments via the
argslist - Use
session$setInputs()to simulate user interactions - Access reactive return values directly by name
- Test edge cases: empty data, NULL inputs, invalid values
Got: Module tests pass with devtools::test().
If fail: testServer() errors with "not a module server function"? Ensure function uses moduleServer() internally. session$setInputs() doesn't trigger reactives? Add session$flushReact() after setting inputs.
Step 3: Write shinytest2 End-to-End Tests
Create tests/testthat/test-app-e2e.R:
test_that("app loads and displays initial state", {
# For golem apps
app <- AppDriver$new(
app_dir = system.file(package = "myapp"),
name = "initial-load",
height = 800,
width = 1200
)
on.exit(app$stop(), add = TRUE)
# Wait for app to load
app$wait_for_idle(timeout = 10000)
# Check that key elements exist
app$expect_values()
})
test_that("filter interaction updates the table", {
app <- AppDriver$new(
app_dir = system.file(package = "myapp"),
name = "filter-interaction"
)
on.exit(app$stop(), add = TRUE)
# Interact with the app
app$set_inputs(`filter1-column` = "cyl")
app$wait_for_idle()
app$set_inputs(`filter1-apply` = "click")
app$wait_for_idle()
# Snapshot the output values
app$expect_values(output = "table")
})
Key patterns:
AppDriver$new()launches the app in headless Chrome- Always use
on.exit(app$stop())to clean up - Module input IDs use the format
"moduleId-inputId" app$expect_values()creates/compares snapshot filesapp$wait_for_idle()ensures reactive updates complete
Got: End-to-end tests create snapshot files in tests/testthat/_snaps/.
If fail: Chrome not found? Set CHROMOTE_CHROME environment variable to Chrome binary path. Snapshots fail on CI but pass local? Check for platform-dependent rendering differences — use app$expect_values() for data snapshots rather than app$expect_screenshot() for visual ones.
Step 4: Record Test Interactively (Optional)
shinytest2::record_test("path/to/app")
This opens the app in a browser with a recording panel. Interact with the app, then click "Save test" to auto-generate test code.
Got: Test file generated in tests/testthat/ with recorded interactions.
If fail: Recorder doesn't open? Check app runs successful with shiny::runApp() first. Recorder needs working app.
Step 5: Set Up Snapshot Management
For snapshot-based tests, manage expected values:
# Accept new/changed snapshots after review
testthat::snapshot_accept("test-app-e2e")
# Review snapshot differences
testthat::snapshot_review("test-app-e2e")
Add snapshot directories to version control:
tests/testthat/_snaps/ # Committed — contains expected values
Got: Snapshot files tracked in git for regression detection.
If fail: Snapshots change unexpected? Run testthat::snapshot_review() to see diffs. Accept intentional changes with testthat::snapshot_accept().
Step 6: Integrate with CI
Add to .github/workflows/R-CMD-check.yaml or create a dedicated workflow:
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y chromium-browser
- name: Set Chrome path
run: echo "CHROMOTE_CHROME=$(which chromium-browser)" >> $GITHUB_ENV
- name: Run tests
run: |
Rscript -e 'devtools::test()'
For golem apps, ensure the app package is installed before testing:
- name: Install app package
run: Rscript -e 'devtools::install()'
Got: Tests pass in CI with headless Chrome.
If fail: Common CI issues: Chrome not installed (add apt-get step), display server missing (shinytest2 uses headless mode default so usually not issue), or timeout on slow runners (increase timeout in AppDriver$new()).
Checks
-
devtools::test()runs all tests without errors - testServer() tests cover module server logic
- shinytest2 tests cover key user workflows
- Snapshot files committed to version control
- Tests pass in CI environment
- Edge cases tested (empty data, NULL inputs, error states)
Pitfalls
- Test UI rendering instead of logic: Prefer
testServer()for logic andapp$expect_values()for data. Only useapp$expect_screenshot()when visual appearance matters — screenshots brittle across platforms. - Module ID format in e2e tests: Setting module inputs via AppDriver? Use
"moduleId-inputId"format (hyphen-separated), not"moduleId.inputId". - Flaky timing: Always call
app$wait_for_idle()afterapp$set_inputs(). Without it, assertions may run before reactive updates complete. - Snapshot drift: Never commit snapshots generated on different platforms (Mac vs Linux). Standardize on CI platform for snapshot generation.
- Missing Chrome on CI: shinytest2 needs Chrome/Chromium. Always include installation step in CI workflows.
See Also
build-shiny-module— create testable modules with clear interfacesscaffold-shiny-app— set up app structure with testing infrastructurewrite-testthat-tests— general testthat patterns for R packagessetup-github-actions-ci— CI/CD setup for R packages (golem apps)
GitHub репозиторий
Frequently asked questions
What is the test-shiny-app skill?
test-shiny-app is a Claude Skill by pjt222. Skills package instructions and resources that Claude loads on demand, so Claude can perform test-shiny-app-related tasks without extra prompting.
How do I install test-shiny-app?
Use the install commands on this page: add test-shiny-app to Claude Code as a plugin, or clone its repository into your skills directory, then restart Claude so it picks up the skill.
What category does test-shiny-app belong to?
test-shiny-app is in the Testing category, tagged testing.
Is test-shiny-app free to use?
Yes. test-shiny-app is listed on AIMCP and free to install. It runs inside Claude, so no separate service account is required to use the skill itself.
Похожие навыки
Этот навык Claude запускает lm-evaluation-harness для тестирования LLM на более чем 60 стандартизированных академических задачах, таких как MMLU и GSM8K. Он предназначен для разработчиков, чтобы сравнивать качество моделей, отслеживать прогресс обучения или сообщать академические результаты. Инструмент поддерживает различные бэкенды, включая модели HuggingFace и vLLM.
Этот навык предоставляет обширные знания по реализации Cloudflare Cron Triggers для планирования запуска Workers с помощью cron-выражений. Он охватывает настройку периодических задач, заданий технического обслуживания и автоматизированных рабочих процессов, а также решение распространенных проблем, таких как неверные cron-выражения и ошибки часовых поясов. Разработчики могут использовать его для настройки планировщиков обработчиков, тестирования cron-триггеров и интеграции с Workflows и Green Compute.
Этот навык Claude предоставляет инструментарий на базе Playwright для тестирования локальных веб-приложений с помощью Python-скриптов. Он позволяет проводить проверку фронтенда, отладку интерфейса, создание скриншотов и просмотр логов, одновременно управляя жизненным циклом сервера. Используйте его для задач автоматизации браузера, но запускайте скрипты напрямую, вместо чтения их исходного кода, чтобы избежать загрязнения контекста.
Этот навык помогает разработчикам завершать готовую работу, проверяя прохождение тестов и предлагая структурированные варианты интеграции. Он направляет рабочий процесс по слиянию, созданию пул-реквестов или очистке веток после завершения реализации. Используйте его, когда ваш код готов и протестирован, чтобы систематически завершать процесс разработки.
