R Programming Quiz: Package Structure
10 questions · exam conditions
0:00
Package StructureQuestion 1 of 10

Package scoretools lists stats in the Imports field of DESCRIPTION. One of its R files defines adjust <- function(x) median(x), but NAMESPACE contains neither importFrom(stats, median) nor import(stats).

What is the most appropriate interpretation and repair?

The Imports field makes every stats function available unqualified, so no namespace change is needed.
The function must be exported from scoretools; adding export(median) will import the implementation from stats.
Declare importFrom(stats, median) or call stats::median(); listing stats in Imports alone does not create that binding.
Move adjust() into a file named stats.R; file names determine which package namespace supplies unqualified functions.
← Back to quizzes

R Programming Quiz

R Programming Quiz: Package Structure

Practice Package Structure in R Programming with focused quiz questions that help you check what you know, review explanations, and build confidence with test-style prompts.

What this quiz covers

This quiz focuses on Package Structure, giving you a quick way to practice the rules, question types, and explanations that matter most for R Programming.

How to use this quiz

Try each quiz question before looking at the correct answer. Use the explanations to review missed ideas, then come back to similar questions until the pattern feels familiar.

All questions

Question 1

Package scoretools lists stats in the Imports field of DESCRIPTION. One of its R files defines adjust <- function(x) median(x), but NAMESPACE contains neither importFrom(stats, median) nor import(stats).

What is the most appropriate interpretation and repair?

  1. The Imports field makes every stats function available unqualified, so no namespace change is needed.
  2. The function must be exported from scoretools; adding export(median) will import the implementation from stats.
  3. Declare importFrom(stats, median) or call stats::median(); listing stats in Imports alone does not create that binding. (correct answer)
  4. Move adjust() into a file named stats.R; file names determine which package namespace supplies unqualified functions.
Explanation: When working with R packages, it's essential to understand that DESCRIPTION and NAMESPACE serve entirely different purposes. The Imports field in DESCRIPTION ensures a package is installed and attached to the search path during your package's load process — but it does not automatically make individual functions available as unqualified names inside your package's own code. For that, you need explicit namespace directives. This is why C is correct: without importFrom(stats, median) in NAMESPACE (or the alternative of calling stats::median() directly), R has no instruction to bind the name median into scoretools's namespace. When adjust() calls median(x), R searches the package namespace first and may not find it, leading to unpredictable behavior or errors depending on the environment. A describes a common misconception — that Imports alone grants unqualified access. It doesn't. Imports in DESCRIPTION is about dependency management, not namespace binding. B conflates exporting with importing. Adding export(median) would attempt to expose a name from scoretools to users, which is the opposite of what's needed; you need to import median into scoretools first. D is entirely fabricated — R determines namespace access through NAMESPACE directives, never through file naming conventions. A useful mental model: think of DESCRIPTION as your package's shopping list (what it needs installed) and NAMESPACE as your package's wiring diagram (what functions are actually connected and usable). Always make sure both are aligned when you use functions from external packages.

Question 2

After installing metricbox, a developer looks in the installed package directory and does not find the original files R/metrics.R and R/format.R. The package's functions still work after library(metricbox).

Which explanation best accounts for this result?

  1. Installation commonly stores R objects in lazy-load databases, so the installed package need not preserve the source package's individual R files. (correct answer)
  2. Installation moves all R source files into man, where the help system evaluates them whenever a function is called.
  3. Installation deletes the R functions after copying them into the user's global environment for later package sessions.
  4. Installation converts each R source file into a vignette, which is then evaluated when the package is attached.
Explanation: When you install an R package, the source files you authored during development are transformed — not simply copied — into a format optimized for loading. Understanding this transformation is key to questions about what an installed package actually contains on disk. During installation, R processes all .R files in the R/ directory and compiles the resulting objects (functions, data, etc.) into a lazy-load database — typically .rdb and .rdx files stored in the package's R/ subdirectory of the installed location. When you call library(metricbox), R loads from this database rather than re-parsing any source files. This is why the package works perfectly even though metrics.R and format.R are nowhere to be found: those source files were never meant to travel with the installed package. Answer A correctly describes this mechanism. Answer B is wrong because the man/ directory holds pre-built documentation (.Rd files), not R source code. Help pages are static text, not an execution environment. Answer C misrepresents how packages work entirely — installation never copies functions into the user's global environment; functions live in the package's own namespace and become accessible only when you attach or reference the package. Answer D confuses vignettes (long-form tutorials stored in vignettes/) with source files; source code is never converted into vignettes during installation. A useful mental model: think of installation as a compilation step. Just as a C program doesn't ship with its .c source files, an installed R package replaces source .R files with a binary-like lazy-load database for efficient loading.

Question 3

A package using testthat contains several files under tests/testthat/, but it has no tests/testthat.R file. The tests pass when a developer opens and runs each test file interactively, yet the package check does not run that suite as intended.

Which structural change is most appropriate?

  1. Move all test files into R/ so package loading evaluates them before exposing the package functions.
  2. Add a tests/testthat.R runner that loads the test framework and calls test_check() for the package. (correct answer)
  3. List every test file in the Collate field so package installation evaluates them after the implementation files.
  4. Place the test files under inst/tests/ so the installation process executes them from the installed package.
Explanation: When working with R package testing infrastructure, the key question to ask is: "How does R CMD check actually discover and execute the test suite?" The answer lies in the entry point file, not the individual test files themselves. The testthat framework requires a specific handshake with R's package checking system. When R CMD check runs, it looks for tests/testthat.R as the top-level runner script. That file typically contains library(testthat) and test_check("yourpackage"), which tells the check system to find and execute all files under tests/testthat/. Without this runner, the check process has no entry point into your suite — even if every individual test file is perfectly written. This is exactly why B is correct: adding tests/testthat.R with the appropriate test_check() call bridges the gap between your test files and the automated checking pipeline. The distractors each reflect a fundamental misunderstanding of where test code belongs. A is wrong because placing test files under R/ would bundle them into the package itself, executing test assertions as part of normal package loading — a serious structural mistake. C is wrong because the Collate field controls the order of source file loading during installation, not test execution; test files should never be in the path Collate manages. D is wrong because inst/tests/ is an older convention associated with different frameworks; R CMD check does not automatically execute files placed there with modern testthat setups. A useful mental model: think of tests/testthat.R as the ignition key — the test files are the engine, but without the key, R CMD check never starts the car.

Question 4

A package repository contains a top-level notes/ directory with large design drafts. The directory is listed in .gitignore, but R CMD build still includes it in the source bundle.

Which change directly prevents that directory from entering the built package while allowing it to remain in the working tree?

  1. Add an appropriate pattern such as ^notes$ to .Rbuildignore; version-control ignore rules do not control package building. (correct answer)
  2. Add notes to the Imports field in DESCRIPTION; undeclared directories are otherwise treated as dependencies.
  3. Add exportPattern("notes") to NAMESPACE; unexported directories are automatically removed from source bundles.
  4. Move notes/ under R/; package-building tools omit non-R files whenever they occur beside R source files.
Explanation: When packaging R code, it helps to remember that two separate systems control what gets ignored: Git's .gitignore governs version control, while .Rbuildignore governs what R CMD build includes in the source tarball. These systems are completely independent, so listing something in one has no effect on the other. Because .Rbuildignore uses regular expressions (not glob patterns), adding ^notes$ anchors the match to a top-level directory named exactly notes, which tells the build system to exclude it from the bundle while leaving the directory untouched in your working tree. That makes A the correct and direct solution. B is wrong because Imports in DESCRIPTION lists other R packages your code depends on — it has nothing to do with directories inside your own repository. Directories are never "declared as dependencies." C is wrong because NAMESPACE controls which R functions and objects are exported from your package's namespace for users. It has no awareness of arbitrary directories and plays no role in filtering files during the build process. D is wrong because placing notes/ inside R/ would actually make things worse — R CMD build processes the R/ directory specifically looking for .R source files, and introducing non-R content there could cause unexpected behavior or errors, not silent exclusion. A useful rule of thumb: whenever you want to keep files in your project but out of the distributed package, .Rbuildignore is always the right tool. Keep a mental separation between "what Git tracks," "what gets built," and "what gets exported."

Question 5

A project directory contains workspace/pkgA/DESCRIPTION, workspace/pkgA/NAMESPACE, and workspace/pkgA/R/fit.R. An analyst wants to build the package but proposes treating workspace/pkgA/R as the package directory because it contains the function definitions.

Which directory should be treated as the package root, and why?

  1. workspace/pkgA/R, because the directory containing the R function files defines the package boundary.
  2. workspace/pkgA, because its DESCRIPTION identifies the package root and its subdirectories supply package components. (correct answer)
  3. workspace, because package tools search its child directories for DESCRIPTION and combine their contents.
  4. workspace/pkgA/DESCRIPTION, because the metadata file itself is passed as the complete package source.
Explanation: When working with R packages, it helps to think of the package as a structured project, not just a collection of files. Every R package has a strict layout defined by R's tooling: a root directory that contains DESCRIPTION, NAMESPACE, and subdirectories like R/, man/, and data/. The root is the anchor point — it's where R CMD build, devtools::build(), and related tools expect to start. workspace/pkgA is the correct package root because it holds the DESCRIPTION file, which is what R's packaging system uses to identify and define the package — its name, version, dependencies, and authorship. The subdirectories (R/, man/, etc.) are components of that package, not the package itself. When you call devtools::install("workspace/pkgA"), R reads DESCRIPTION at that level and then looks inside R/ for source files automatically. A mistakes the part for the whole. workspace/pkgA/R/ contains function definitions, but it has no DESCRIPTION or NAMESPACE — R tools would fail to recognize it as a package root at all. C is wrong because workspace/ is simply a project container. R doesn't combine child directories into a single package; each package must have its own self-contained root. D confuses a file with a directory. You pass a directory path to package tools, not the DESCRIPTION file itself — the file lives inside the root, it doesn't replace it. A useful rule of thumb: wherever DESCRIPTION lives, that directory is the package root. On exam questions, find the DESCRIPTION file first, then move one level up — that parent is always your answer.

Question 6

A package uses a small lookup object only inside its own functions. Users should not load the object with data(). The script that downloads and cleans the original data is useful to maintainers but should not be included in the built package.

Which organization best matches these requirements?

  1. Store the object in data/lookup.rda and the preparation script in R/prepare_lookup.R so both are loaded for users.
  2. Store the object in R/sysdata.rda and keep the preparation script in an ignored development directory such as data-raw/. (correct answer)
  3. Store the object in man/lookup.rda and the preparation script in tests/ so documentation tools install both files.
  4. Store the object in inst/lookup.rda and the preparation script in NAMESPACE so only package functions can access them.
Explanation: When organizing an R package, you need to match each type of file to the directory designed for its purpose — internal data, user-facing data, documentation, and development artifacts each have a designated home. For internal package data that users should never access directly via data(), R provides a special location: R/sysdata.rda. Objects stored there are automatically available to your package's functions but are invisible to users. For development scripts you want to keep for maintainers but exclude from the built package, data-raw/ is the conventional solution — you list it in .Rbuildignore so it never ships to end users. This combination makes B exactly right: internal object in R/sysdata.rda, preparation script tucked away in data-raw/. A is wrong because data/lookup.rda is explicitly for user-facing datasets — anything placed there becomes loadable with data(), which directly violates the requirement that users shouldn't access the object. C is wrong on two counts: man/ is reserved for documentation files (.Rd files generated by tools like roxygen2), not data storage, and tests/ is for unit tests, not preparation scripts. Placing data there would confuse package tooling. D is wrong because inst/ is for arbitrary files that are included in the built package and installed alongside it — the opposite of what you want for a private script. NAMESPACE is a declaration file for imports and exports, not a place to store scripts at all. A useful rule of thumb: if it's internal data, use R/sysdata.rda; if it's a development-only script, use data-raw/ plus .Rbuildignore.

Question 7

Package readspec needs to ship schema.json as an auxiliary file. The maintainer places it at inst/extdata/schema.json and wants package code to find it after installation without assuming the library's physical location.

Which approach correctly uses this package structure?

  1. Read inst/extdata/schema.json directly, because the inst prefix remains part of every installed package path.
  2. Move the file to R/extdata/schema.json, then obtain it by inspecting the environment of an exported function.
  3. Export schema.json through NAMESPACE, then refer to the file by its exported object name.
  4. Use system.file("extdata", "schema.json", package = "readspec"), because contents of inst are copied beneath the installed package root. (correct answer)
Explanation: When working with auxiliary files in R packages, the key concept to understand is what happens to the inst/ directory during package installation. R's build system treats inst/ as a staging area — everything inside it gets copied directly into the package's root directory, with the inst/ prefix stripped away. So inst/extdata/schema.json becomes extdata/schema.json relative to the installed package root. This is exactly why system.file("extdata", "schema.json", package = "readspec") is the correct approach (D). The function constructs the full, absolute path to the file at runtime by locating wherever R installed the readspec package on that particular system — no hardcoded paths, no assumptions about library location. Choice A fails because it inverts the installation logic. The inst/ prefix disappears after installation, so any code that references inst/extdata/... directly will produce a broken path on any user's machine. Choice B introduces a fictional convention — R does not treat R/extdata/ as a special directory, and function environments have nothing to do with file discovery. Trying to locate a data file by inspecting a function's environment would never work. Choice C confuses file assets with R objects. NAMESPACE manages exported functions and objects, not files. You cannot export a .json file through NAMESPACE or reference it by an object name — those are entirely different systems. A good rule of thumb: whenever a package needs to ship a non-R file (JSON, CSV, text templates), store it under inst/extdata/ and always retrieve it at runtime with system.file(). This pattern is idiomatic R and appears frequently on package development questions.

Question 8

A maintainer uses roxygen2 comments above calculate_score() in R/score.R. The generated file man/calculate_score.Rd is already present. The maintainer changes the function's arguments and updates only the roxygen2 comments.

What should the maintainer do before checking the package?

  1. Edit only NAMESPACE, because namespace generation automatically rewrites the help database from the function signature.
  2. Move the roxygen2 comments into man/, because comments in R/ are ignored by documentation generators.
  3. Run the documentation-generation step so the .Rd file, and any generated namespace directives, reflect the updated comments. (correct answer)
  4. Delete the entire man/ directory, because package checking renders help pages directly from roxygen2 comments at load time.
Explanation: Whenever you see a question about R package documentation workflows, think about the relationship between source and derived files. In a roxygen2-based package, the .Rd files in man/ and the NAMESPACE file are generated artifacts — they are produced from the @ tags in your R/ source files, not maintained by hand. This separation is the core concept being tested here. When you update roxygen2 comments (for example, changing @param tags after modifying arguments), the existing man/calculate_score.Rd still reflects the old comments. The only way to synchronize everything is to run the documentation-generation step — typically devtools::document() or roxygen2::roxygenise() — which rewrites the .Rd files and regenerates NAMESPACE directives like @export. That's exactly what C describes, and why it's correct. A is wrong because NAMESPACE doesn't control help page content, and editing it manually won't update the .Rd file at all. Namespace generation and documentation generation are both handled by running roxygen2 — neither one triggers the other in isolation. B has the workflow completely backwards. Roxygen2 reads comments from R/ and writes to man/. Manually placing comments in man/ serves no purpose; the generator would simply overwrite anything placed there. D is a trap: deleting man/ is unnecessary and breaks things if you forget to regenerate. Package checking does not render help pages live from source comments — it expects fully built .Rd files to be present. Your study takeaway: in any roxygen2 workflow question, remember that source lives in R/, generated files live in man/ and NAMESPACE, and running document() is what bridges them.

Question 9

In package cachekit, b-cache.R contains the top-level assignment default_cache <- make_cache(). The function make_cache() is defined in z-helpers.R. During installation, the assignment is evaluated before make_cache() has been defined.

Which package-structure change most directly specifies the required source-file order?

  1. Add export(make_cache) to NAMESPACE so the function becomes visible while the other file is evaluated.
  2. List cachekit in its own Imports field so earlier files can import functions defined by later files.
  3. Move both files into inst/R so installation copies them before evaluating their top-level assignments.
  4. Add a Collate field to DESCRIPTION that places z-helpers.R before b-cache.R during code loading. (correct answer)
Explanation: When working with R packages, you need to understand how R decides the order in which source files are loaded during R CMD INSTALL or devtools::load_all(). By default, R processes files alphabetically — which means b-cache.R runs before z-helpers.R, causing the top-level assignment default_cache <- make_cache() to fail because make_cache() hasn't been defined yet. The question is asking which mechanism directly controls that loading sequence. The Collate field in DESCRIPTION is precisely the tool designed for this purpose. By listing z-helpers.R before b-cache.R in Collate, you explicitly tell R's build system the order to source the files, ensuring make_cache() exists when default_cache is assigned. That makes D the correct answer. A is wrong because export() in NAMESPACE controls what users of your package can access — it governs the package's public API, not the internal loading order of source files. Exporting a function doesn't move its definition earlier in time. B is a logical contradiction: a package cannot import from itself via its own Imports field. Imports specifies external package dependencies, not intra-package file ordering. C is wrong because inst/R is a directory for auxiliary scripts that are not automatically sourced during package loading. Files there must be manually source()d by users and play no role in the build-time evaluation sequence. A good study tip: whenever you see a question about file evaluation order inside an R package, think Collate. It's the one field that directly sequences source files — alphabetical order is just the default that Collate overrides.

Question 10

A maintainer has an R Markdown tutorial that explains a multi-step workflow and should be built as long-form package documentation. The tutorial uses knitr and must be associated with the source package rather than treated as an ordinary exported function.

Which package organization is most appropriate?

  1. Place the tutorial in R/ and add its file name to NAMESPACE, allowing package attachment to render the document.
  2. Place the tutorial in man/ and add Imports: rmarkdown, causing the help system to execute it as an .Rd page.
  3. Place the tutorial in vignettes/ and declare the needed vignette builder and supporting package metadata in DESCRIPTION. (correct answer)
  4. Place the tutorial in tests/ and add a Collate entry, causing package checks to install it as user documentation.
Explanation: When working with R packages, it helps to think about the purpose each directory serves. R enforces a clear separation between code, documentation, and supplementary learning materials — and questions like this test whether you know which organizational slot fits which content type. Long-form documentation intended to walk users through a workflow belongs in vignettes/. Vignettes are the official R mechanism for tutorials, guides, and narrative documentation that goes beyond what a ?function help page can offer. To wire everything together, you declare the vignette builder (e.g., VignetteBuilder: knitr) and any required packages (e.g., Suggests: knitr, rmarkdown) in the DESCRIPTION file. This is exactly what option C describes, making it the correct choice. Option A is wrong because R/ is reserved for exportable R source code — functions and objects. The NAMESPACE file controls what those functions expose to users, not how documentation is rendered. Placing an .Rmd file there and listing it in NAMESPACE is nonsensical to R's build system. Option B confuses vignettes with help pages: man/ holds .Rd files generated from roxygen comments, and the help system renders static reference documentation, not executable R Markdown tutorials. Adding Imports: rmarkdown wouldn't change that behavior. Option D misuses tests/, which is for automated testing via frameworks like testthat. The Collate field in DESCRIPTION controls source file load order, not documentation installation. A good study habit here: memorize the four core directories (R/, man/, vignettes/, tests/) and their single, distinct purposes. Exam distractors often swap these roles, so knowing what each directory cannot do is just as important as knowing what it can.