Science Score: 26.0%
This score indicates how likely this project is to be science-related based on various indicators:
-
○CITATION.cff file
-
✓codemeta.json file
Found codemeta.json file -
✓.zenodo.json file
Found .zenodo.json file -
○DOI references
-
○Academic publication links
-
○Committers with academic emails
-
○Institutional organization owner
-
○JOSS paper metadata
-
○Scientific vocabulary similarity
Low similarity (16.8%) to scientific vocabulary
Keywords
functional-programming
property-based-testing
r
rstats
Last synced: 5 months ago
·
JSON representation
Repository
Property Based Testing in R
Basic Info
- Host: GitHub
- Owner: armcn
- License: other
- Language: R
- Default Branch: main
- Homepage: https://armcn.github.io/quickcheck
- Size: 3.97 MB
Statistics
- Stars: 28
- Watchers: 1
- Forks: 1
- Open Issues: 4
- Releases: 4
Topics
functional-programming
property-based-testing
r
rstats
Created about 4 years ago
· Last pushed 8 months ago
Metadata Files
Readme
Changelog
License
README.Rmd
---
output: github_document
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```
# quickcheck
[](https://CRAN.R-project.org/package=quickcheck)
[](https://github.com/armcn/quickcheck/actions/workflows/R-CMD-check.yaml)
[](https://app.codecov.io/gh/armcn/quickcheck?branch=main)
[](https://cran.r-project.org/package=quickcheck)
# Overview
Property based testing in R, inspired by [QuickCheck](https://en.wikipedia.org/wiki/QuickCheck). This package builds on the property based testing framework provided by [`hedgehog`](https://github.com/hedgehogqa/r-hedgehog) and is designed to seamlessly integrate with [`testthat`](https://testthat.r-lib.org).
## Installation
You can install the released version of `quickcheck` from [CRAN](https://CRAN.R-project.org) with:
```{r, eval=FALSE}
install.packages("quickcheck")
```
And the development version from [GitHub](https://github.com/) with:
```{r, eval=FALSE}
# install.packages("remotes")
remotes::install_github("armcn/quickcheck")
```
# Usage
The following example uses `quickcheck` to test the properties of the base R `+` function. [Here](https://fsharpforfunandprofit.com/posts/property-based-testing/) is an introduction to the concept of property based testing, and an explanation of the mathematical properties of addition can be found [here](https://www.khanacademy.org/math/cc-sixth-grade-math/cc-6th-factors-and-multiples/properties-of-numbers/a/properties-of-addition).
```{r}
library(testthat)
library(quickcheck)
test_that("0 is the additive identity of +", {
for_all(
a = numeric_(len = 1),
property = function(a) expect_equal(a, a + 0)
)
})
test_that("+ is commutative", {
for_all(
a = numeric_(len = 1),
b = numeric_(len = 1),
property = function(a, b) expect_equal(a + b, b + a)
)
})
test_that("+ is associative", {
for_all(
a = numeric_(len = 1),
b = numeric_(len = 1),
c = numeric_(len = 1),
property = function(a, b, c) expect_equal(a + (b + c), (a + b) + c)
)
})
```
Here we test the properties of the [`distinct`](https://dplyr.tidyverse.org/reference/distinct.html)
function from the [`dplyr`](https://dplyr.tidyverse.org/index.html) package.
```{r}
library(dplyr, warn.conflicts = FALSE)
test_that("distinct does nothing with a single row", {
for_all(
a = any_tibble(rows = 1L),
property = function(a) {
distinct(a) %>% expect_equal(a)
}
)
})
test_that("distinct returns single row if rows are repeated", {
for_all(
a = any_tibble(rows = 1L),
property = function(a) {
bind_rows(a, a) %>%
distinct() %>%
expect_equal(a)
}
)
})
test_that("distinct does nothing if rows are unique", {
for_all(
a = tibble_of(integer_positive(), rows = 1L, cols = 1L),
b = tibble_of(integer_negative(), rows = 1L, cols = 1L),
property = function(a, b) {
unique_rows <- bind_rows(a, b)
distinct(unique_rows) %>% expect_equal(unique_rows)
}
)
})
```
## Quickcheck generators
Many generators are provided with `quickcheck`. Here are a few examples.
### Atomic vectors
```{r}
integer_(len = 10) %>% show_example()
character_alphanumeric(len = 10) %>% show_example()
posixct_(len = 10, any_na = TRUE) %>% show_example()
```
### Lists
```{r}
list_(a = constant(NULL), b = any_undefined()) %>% show_example()
flat_list_of(logical_(), len = 3) %>% show_example()
```
### Tibbles
```{r}
tibble_(a = date_(), b = hms_(), rows = 5) %>% show_example()
tibble_of(double_bounded(-10, 10), rows = 3, cols = 3) %>% show_example()
any_tibble(rows = 3, cols = 3) %>% show_example()
```
## Hedgehog generators
`quickcheck` is meant to work with `hedgehog`, not replace it. `hedgehog` generators
can be used by wrapping them in `from_hedgehog`.
```{r}
library(hedgehog)
is_even <-
function(a) a %% 2 == 0
gen_powers_of_two <-
gen.element(1:10) %>% gen.with(function(a) 2^a)
test_that("is_even returns TRUE for powers of two", {
for_all(
a = from_hedgehog(gen_powers_of_two),
property = function(a) is_even(a) %>% expect_true()
)
})
```
Any `hedgehog` generator can be used with `quickcheck` but they can't be composed
together to build another generator. For example this will work:
```{r}
test_that("powers of two and integers are both numeric values", {
for_all(
a = from_hedgehog(gen_powers_of_two),
b = integer_(),
property = function(a, b) {
c(a, b) %>%
is.numeric() %>%
expect_true()
}
)
})
```
But this will cause an error:
```{r}
test_that("composing hedgehog with quickcheck generators fails", {
tibble_of(from_hedgehog(gen_powers_of_two)) %>% expect_error()
})
```
A `quickcheck` generator can also be converted to a `hedgehog` generator which can
then be used with other `hedgehog` functions.
```{r}
gen_powers_of_two <-
integer_bounded(1L, 10L, len = 1L) %>%
as_hedgehog() %>%
gen.with(function(a) 2^a)
test_that("is_even returns TRUE for powers of two", {
for_all(
a = from_hedgehog(gen_powers_of_two),
property = function(a) is_even(a) %>% expect_true()
)
})
```
## Fuzz tests
Fuzz testing is a special case of property based testing in which the only
property being tested is that the code doesn't fail with a range of inputs.
Here is an example of how to do fuzz testing with `quickcheck`. Let's say we want
to test that the `purrr::map` function won't fail with any vector as input.
```{r}
test_that("map won't fail with any vector as input", {
for_all(
a = any_vector(),
property = function(a) purrr::map(a, identity) %>% expect_silent()
)
})
```
## Repeat tests
Repeat tests can be used to repeatedly test that a property holds true for many
calls of a function. These are different from regular property based tests
because they don't require generators. The function `repeat_test` will call
a function many times to ensure the expectation passes in all cases. This kind
of test can be useful for testing functions with randomness.
```{r}
test_that("runif generates random numbers between a min and max value", {
repeat_test(
property = function() {
random_number <- runif(1, min = 0, max = 10)
expect_true(random_number >= 0 && random_number <= 10)
}
)
})
```
Owner
- Name: Andrew R McNeil
- Login: armcn
- Kind: user
- Location: Toronto, ON
- Company: Sanofi
- Twitter: armcn_
- Repositories: 2
- Profile: https://github.com/armcn
R Shiny Developer
GitHub Events
Total
- Issues event: 4
- Watch event: 1
- Push event: 5
- Pull request event: 1
- Create event: 1
Last Year
- Issues event: 4
- Watch event: 1
- Push event: 5
- Pull request event: 1
- Create event: 1
Committers
Last synced: 10 months ago
Top Committers
| Name | Commits | |
|---|---|---|
| Andrew McNeil | a****l@g****m | 91 |
Issues and Pull Requests
Last synced: 7 months ago
All Time
- Total issues: 21
- Total pull requests: 3
- Average time to close issues: 4 months
- Average time to close pull requests: 3 months
- Total issue authors: 6
- Total pull request authors: 2
- Average comments per issue: 0.24
- Average comments per pull request: 0.0
- Merged pull requests: 3
- Bot issues: 0
- Bot pull requests: 0
Past Year
- Issues: 4
- Pull requests: 1
- Average time to close issues: 10 days
- Average time to close pull requests: 9 months
- Issue authors: 4
- Pull request authors: 1
- Average comments per issue: 0.25
- Average comments per pull request: 0.0
- Merged pull requests: 1
- Bot issues: 0
- Bot pull requests: 0
Top Authors
Issue Authors
- armcn (16)
- eitsupi (1)
- atsyplenkov (1)
- etiennebacher (1)
- torbjorn (1)
Pull Request Authors
- jonocarroll (2)
- armcn (2)
Top Labels
Issue Labels
Pull Request Labels
Packages
- Total packages: 1
-
Total downloads:
- cran 506 last-month
- Total dependent packages: 1
- Total dependent repositories: 20
- Total versions: 5
- Total maintainers: 1
cran.r-project.org: quickcheck
Property Based Testing
- Homepage: https://github.com/armcn/quickcheck
- Documentation: http://cran.r-project.org/web/packages/quickcheck/quickcheck.pdf
- License: MIT + file LICENSE
-
Latest release: 0.1.3
published over 2 years ago
Rankings
Dependent repos count: 6.3%
Stargazers count: 12.9%
Dependent packages count: 18.2%
Average: 19.9%
Forks count: 27.7%
Downloads: 34.5%
Maintainers (1)
Last synced:
7 months ago
Dependencies
DESCRIPTION
cran
- data.table * imports
- hedgehog * imports
- hms * imports
- magrittr * imports
- purrr * imports
- stats * imports
- testthat >= 3.0.0 imports
- tibble * imports
- covr * suggests
- dplyr * suggests
- knitr * suggests
- rmarkdown * suggests
.github/workflows/R-CMD-check.yaml
actions
- actions/checkout v2 composite
- actions/upload-artifact main composite
- r-lib/actions/check-r-package v1 composite
- r-lib/actions/setup-r v1 composite
- r-lib/actions/setup-r-dependencies v1 composite
.github/workflows/pkgdown.yml
actions
- actions/checkout v2 composite
- r-lib/actions/setup-pandoc v2 composite
- r-lib/actions/setup-r v2 composite
- r-lib/actions/setup-r-dependencies v2 composite
.github/workflows/test-coverage.yaml
actions
- actions/checkout v2 composite
- r-lib/actions/setup-r v1 composite
- r-lib/actions/setup-r-dependencies v1 composite