
# Reproducible Research with R Packages - exRcises
## Week 1
### Introduction
#### Exercise: have you ever encountered any of the following: (put your name after the `|` in the table if it sounds familiar)
| Did you ever... | _name_ |
|:---|:---|
Did you ever have problems running research software written by a colleague? |
Did you ever have problems running your own software? |
Are you sometimes scared of editing your code, just in case you “break” it? |
Did you ever have to re-do all the figures in your paper manually? |
Do you suspect that some parts of your code may not be working as you want them to? |
Do you feel that you are losing control about how your code is growing? |
### Getting started
#### Exercise: edit the function, and reload the package.
The default package generates `Hello, world!` when the only function`hello()` is called.
1. Change this function to generate a different output. (Have fun with it, perhaps add an argument or two!)
2. Build and install the package, and call the function again to see that it works differently.
#### Exercise: tell me how you load your functions?
1. How do you usually work with functions?
A. Do you source them from an external file?
B. Do you usually work on a single, long script?
C. .... other (please share!)
2. Can you think of any advantage of using packages instead?
### Accessing packages
#### Exercise: find a package on github, bitbucket, or gitlab and install it with `devtools`.
If you have trouble finding a package, [try this one](https://github.com/PabRod/kinematics).
1. What package did you install? Share a link!
2. What code did you use to install it?
3. Did it work? What problems did you encounter?
4. Bonus: take a look at the `DESCRIPTION` file of the package you installed (you find this file in the root of the package, on the GitHub/BitBucket/GitLab page). Did you notice that other packages mentioned in this file were installed also?
### Licenses
#### Exercise: what license does your favorite package have?
Use `packageDescription("myFavoritePackage", fields = "License")` to check the license of (a) package(s) you like to use.
What licenses do you find?
#### Exercise: look at licenses on [choosealicense.com](https://choosealicense.com/).
What license would you choose? What is important to you?
#### Exercise: change the license of your package.
1. Change the license of your package to Apache, using `usethis::use_apache_license()`. Look at the `DESCRIPTION` and `License` files and see how they have changed.
2. Change the license of your package to the license you want to use. What function did you use?
### Writing our own functions
#### Exercise: Open the DESCRIPTION file. What do you see here?
Take 5 minutes to edit this file with the information it asks. In particular, edit the following fields (when needed): Title, Version, Author, Maintainer, Description. For now, ignore the rest.
### Homework after week 1
Create a package using your own R project, if you have one (see the last point below if you do not have one). Create functions in the R folder of that package.
Remember the following:
* When you are using external functions inside your package, add double colons `::` before calling that function
* Separate out different functions, think about main functions and helper functions
* If you start from a script, you can keep the leftovers (if there are any after separating out functions) in a script that calls your package's functions and runs your workflow.
* It is very good if **at least one of your functions gives an output** (so, it doesn't just "do" something, like print `Hello World`): it actually creates a data frame, or a vector, or an object of some other kind! We will see why next week.
* Don't forget through `Install (and Restart)` whenever you change anything.
* If you are creating your own package, don't forget to update the `DESCRIPTION` file.
* If you are not using your own project, take some time to improve the current `make_groups` function and perhaps add another function.
Don’t worry if you run into issues, this is expected. See if you can fix them, but don't be afraid to bring them next week, so we can solve them together.
## Week 2
### Testing
#### Exercise: what happened?
Run `usethis::use_testthat()` in the console, and take a look at its output. Also take a look at your folder system (press the refresh button if needed).
What happened?
#### Exercise: what does this test do?
Open a newly created testfile (after running `usethis::use_test([function])`, you will find it in `/tests/testthat/`) and take a look at its contents. It should contain something like this:
```r
test_that("multiplication works", {
expect_equal(2 * 2, 4)
})
```
This is just an example test, that was created to make your life easier. You can use it as a template for writing your own tests.
Take 10 minutes to:
- Figure out what is happening inside this test. Can you understand it?
- Write another test, just below this one, that checks that addition also works. Tip: you can copy-paste and edit the current test.
#### Exercise: write your own test.
Now it is your turn to write a test. With a vector of 6 names as input, check that the output of `make_groups()` is a matrix with 3 rows and 2 columns.
Tip 1: tests can contain multiple assertions.
Tip 2: the functions `nrow` and `ncol` may come in handy.
#### Exercise: test an uneven number.
Write a new test that passes an uneven number of names to `make_groups`.
Run the test again. What happened?
#### Exercise: Write a test using three different `expect_` functions.
Write one or multiple tests, based on a function of your choice, in which you use three different assertion types. For instance, `expect_error`, or `expect_length`. See [the documentation](https://testthat.r-lib.org/reference/index.html) for a list of functions.
### Test-coverage
#### Exercise: Check and increase your test coverage
If you have not installed the `covr` package, do so now: `install.packages("covr")`.
1. Make a coverage report with `covr::report()`. What is your coverage percentage?
2. Look at the coverage of an individual function. Does the coverage percentage make sense to you?
3. Write a test for a part of the function that you think is not yet covered. Re-run `covr::report()`. Did you increase your coverage?
### Homework after week 2
In this coming week, we would like you to apply the things you learned today to your own package. Start with the following steps:
1. Setup test infrastructure for your package with `usethis::use_testthat()`
2. Create a test using `usethis::use_test("test-context")`
Then, please write tests for one or more of your functions. You can do this as you see fit. For example:
- Write multiple tests for a single function, to test that the function deals well with multiple kinds of input. Remember you can put multiple assertions in a single test (an assertion is stating an expectation, e.g. `expect_equal`, `expect_true`).
- Check if your function produces specific error messages (using e.g. `expect_error`).
- Write a test for (part of) your workflow, in which multiple functions are used (remember that this is called *integration testing*).
- Use `covr::report()` to identify parts of your package that could benefit from more tests.
As you do this, here are some useful links:
- The collaborative document for today: https://tinyurl.com/Rbackup2
- Testthat documentation (including a description of all expect_ functions): https://testthat.r-lib.org/reference/index.html
Finally, and most importantly, do continue to develop the functions in your package. You can do this together with newly developed tests: your tests can help you confirm that functions still work as expected while you edit (refactor) them.
## Week 3
### Documentation
Take 5 minutes to edit the skeleton with real documentation. In particular:
1. Add a title.
1. Describe, below the title, what the function does.
1. Describe the parameter names.
1. Describe the output that is returned.
1. Ignore @export.
1. Delete @examples.
### Dependencies
#### Exercise: Add dependencies to the description file, using `usethis::use_package()`.
For practice only:
- Place one package in Imports, and one in Suggests.
- Specify a minimum version.
- Notice that you can delete them again!
#### Exercise: run 'Check'
Run the 'Check' function (either with the button, or with `devtools::check()`. Look for information about your dependencies in the resulting text. Are any dependencies missing, or declared dependencies unused? Copy the warnings you get (only those about dependencies!) below.
### Data
#### Exercise: add data to your package
First, some reference information:
```mermaid
flowchart LR
id1(Does the user need access?) --Yes--> id6(Store it in data/)
id3(Is the data in .Rda format?)--Yes--> id1
id1 --No, but tests do--> id5(Store it in tests/)
id1 --No, but functions do--> id4(Store it in R/sysdata.Rda*)
id3 --No--> id8(But can it be?)
id8 --Yes, with some work --> id9(Document the process in data-raw/**)
id8 --No, it shouldn't--> id7(Store it in inst/extdata)
```
(If the chart does not render, this is what it is supposed to show:)

`*`) `R/sysdata.Rda` is a file dedicated to (larger) data needed by your functions. [Read more about it here](https://r-pkgs.org/Data.html#sec-data-sysdata).
`**`) `data-raw/` is a folder dedicated to the origin and cleanup of your data. [Read more about it here](https://r-pkgs.org/Data.html#sec-data-data-raw).
**And now the exercise: add data to your package!**
- Do you need raw data as part of your package?
- Create a folder `inst/extdata`, and save the files here. Note that a user will be able to access this data.
- When loading the data, do not describe the path as you usually would. Instead, use something like:
```r
filepath <- system.file("extdata", "names.csv", package = "mysterycoffee")
names <- read.csv(filepath)
```
- Do you need data you can store in your package as an .Rda file?
- Create the object
- Store it with `usethis::use_data(object_name)`
- Verify the object is now stored in the `data/` folder
- Document the data (Do this *after* activating Roxygen!)
- Create a new R file called `data.R`: `usethis::use_r("data")` (`data.R` is an example; you may call this whatever you want)
- In this file, document the data object, using this example:
```
#' Title
#'
#' A short description.
#'
#' @format What format is the data in?
#' @source Where did it come from? \url{https://google.com}
"object_name"
```
- Don't forget to call `devtools::document()` to generate the documentation file and add this data to the package namespace.
### Homework after week 3
As you perhaps already expect, the homework for this week is… write documentation for your package! Some additional tips and points of attention:
- Make sure you are clear on what functions are for the user — label them with `@export` — and what functions are helper functions.
- For the exported functions: insert a Roxygen skeleton (Code > Insert Roxygen Skeleton), and fill it out. Do explore the Roxygen documentation (https://roxygen2.r-lib.org/) and experiment with different tags.
- After documenting the package (e.g. with `devtools::document()` or `roxygen2::roxygenise()`), explore what the help pages for your functions look like, by pulling them up as you normally would with `?function_name`. Adjust as necessary.
Aside from the Roxygen documentation, do write a README.md file with some basic information about your package! This will be the first thing potential users see, so what do you want them to know?
Finally, make sure the dependencies of your package are clearly stated in the DESCRIPTION file. Note also that running a Check will only check your code for functions that are labeled with `packagename::function_name()`, and it will not detect any functions from external packages if they are not labeled correctly. Go through your code to be extra sure that functions are called correctly and you are not missing dependencies!
Remember that next week we will share our respective packages. Your package will not be complete and that is completely expected and perfectly OK. However, it would be nice if your package has at least one function that works and is well documented!
### Vignettes
#### Exercise: add a vignette.
- Use `usethis::use_vignette(vignette-name)` to create a vignette fit for your package.
- In the .Rmd file that is now created, add a code chunk that uses a function from your package. (Feel free to add some descriptive text, too!)
- Preview the vignette with the Knit button.
- Create the vignette with `devtools::build_rmd("vignettes/vignette-name.Rmd")`
- Verify that the vignette was built: a .html file should now appear in the vignettes/ folder.
### Share your package (final exercise)
As the final exercise today, we will share the packages we created with each other.
- On your GitHub profile, add a new repository (with the name of your package).
- Upload the entire package to the repository.
- Ensure your README file contains:
- Instructions to install the package
- A first function or small script to run (or: a link to the Vignette that contains this).
- Place the link to the package in the table below.
- Find a package from another user, install it and run their example. Comment BELOW the table (otherwise it will become a mess).
#### Packages
| Name | Link to repository |
|:--|:--|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
#### Comments from users
### Documenting your package
### Exercise: what is in a README?
[Take a look at this README file](https://github.com/PabRod/kinematics)
What subjects are addressed in this README?
Is there anything that you miss, as a potential user?
## Week 4
### Vignettes
### Sharing our packages