Giter VIP home page Giter VIP logo

assertions's People

Contributors

selkamand avatar

Watchers

 avatar

assertions's Issues

Why do we force first user argument to be named 'x'?

I think when creating an assertion, it would be better to just use the original argument names from the function your wrapping.

This would unify the way users can access argument names using glue expressions in default_error_msg arguments

Don't export 'advanced' is_ functions

is_string_advanced and is_number_advanced are exported, but they're pretty much useless to most users. ensure any advanced 'is' functions are not exported.

add set comparison assertion

We need to be able to check if all elements of a vector are one of a valid set

look into is_subset

maybe create assert_subset

could also be named something like assert_all_are_in

Add explanation of low code-cov

Robust assertion packages should have extremely high unit-test coverage

Unfortunately, because assertion function from this package are created with a function assert_create the unit tests aren't considered to cover the assertion creation statements

Add matrix example to assert_character

difference between assert_character and assert_character_vector is obscure

Add documentation indicating the difference and a matrix example passing in assert_character but failing in assert_character_vector

Allow user supplied msg's to access environment where the assertion was called

If a user calls assert_includes(x, required, msg = "please ensure 'x' includes these very important elements: {required}") they probably assume evuation should have access to 'required'. By default this is not the case

For user msg overrides we should evaluate in their environment. For assertion creation functions, in which were defining a default error message, evaluation can remain as is.

Add consistent way to access user-defined arguments from function passed to

we have arg_name to access deparse(substitute(x)) - called from within the assertion,
but how can we get the relevant 'name' of arg2 such that if a user calls assert_test(1:5, 10:12) the error message says
'1:5 is our first argument, 10:12 is our second'

# Create an assertion-powering function
test_advanced <- function(x, arg2){
  return("{arg_name} is our first argument. {name(arg2)} is our second.")
}

assert_test <- assert_create(
  test_advanced
  )

Create assert_create_advanced - which allows `func` to return a string describing the error

might need to make a new function

assert_create_advanced()

that only takes a function, and expects func to return TRUE if assertion passes, or a STRING if it should throw an error (where STRING = the error message)

Its just too useful to not include when building assertions that can take vector inputs, since the error message often needs to list all the elements that fail (or the count of how many failed if there are too many vector inputs)

Remove assert_file_permissions

Current implementation is not OS-independent. The safest way to test if a file is readable is actually to just try and read a small part of it in a trycatch. Should remove and consider re-implementing later

Switch expect_error to expect_snapshot to allow easier tweaks to error messages

Example

cli::test_that_cli("assert_list() works", configs = "plain", {

  # Works for lists
  expect_true(assert_list(list(1, 2, 3)))
  expect_true(assert_list(list()))

  # Aborts for non-list objects
  expect_snapshot(assert_list(1), error = TRUE)
  expect_snapshot(assert_list(1.5), error = TRUE)
  expect_snapshot(assert_list('abc'), error = TRUE)
  expect_snapshot(assert_list(c(1, 2, 3)), error= TRUE)
  expect_snapshot(assert_list(mtcars), error= TRUE)
  expect_snapshot(assert_list(factor(c(1, 2, 3))), error = TRUE)

  # Error messages use variable name of passed arguments
  y <- c(1, 2, 3)
  expect_error(assert_list(y), "'y'", fixed = TRUE)

  # Custom error messages work
  expect_error(assert_list(1, msg = "Custom error message"), "Custom error message")
})

Ensure code injection is impossible

Currently we evaluate custom and predefined error messages as glue strings. This can include code written between curled braces. Now code that gets evaluated should only ever be written by package devs. The question is, can an end-user by supplying string arguments that contain code snippets somehow get it evaluated.

We should thoroughly test this for prebuilt, and custom built functions and see if we can get user - injected code available. If so we'll have to switch glue to glue_safe which evaluates variables but won't run code.

Recode assert file functions

fix assert_file_extension and other file functions to take advantage ability of func to return strings defining error messages

Decide vectorisation rules and document somewhere

What assertions should work on vectors vs scalars.

  1. assert_string, assert_number, and other assert_type functions should treat vectors as a single, whole object
  2. assert_compare / assert_between, etc - should these operate individually on each element in vector or only work on numbers?
  3. assert_equal should probably consider the vectors as whole objects ... but may require more thought

Its a tricky problem and worth doing more thought to devise a general rule and function naming structure that will work intuitively for end-users

Rethinking 'has_' assertions

Is assert_has_no_duplicates and friends a little verbose?

I think assert_no_duplicates would suffice

Similarly: assert_has_no_missing_values would be better as assert_no_missing_values or even assert_no_missing

Make examples cran compatible

In our examples there are lots of \dontrun{assert_number()} style code to get around the fact if examples are run they will throw errors

I need to dig up the cran additional checks checklist which had instructions on best ways to deal with this ... maybe I'll wrap assertions in try?

assertive and assertthat both solve this problem by using a helper/different function. For example in assertthat you see a lot of 'see_if' which does the same thing but doesnt throw an error. I could add a function like that ... but would prefer not to bloat the interface

msg evaluation in wrong Environment when assert call is wrapped within a function

library(assertions)

# Fails when assert is called in a function
foo <- function(x){
  bob <- 10
  assert(length(bob) == 2, msg = "bob should be 2, not {bob}")
}

foo()
#> Error in "fun(..., .envir = .envir)": ! Could not evaluate cli `{}` expression: `bob`.
#> Caused by error in `eval(expr, envir = envir)`:
#> ! object 'bob' not found

# Works when assert not called in a function
bob <- 10
assert(length(bob) == 2, msg = "bob should be 2, not {bob}")
#> Error:
#> ! bob should be 2, not 10

Created on 2023-02-24 by the reprex package (v2.0.1)

Fix vectorisation of assert_files_exist

Make assert_file_exists and assert_directory_exists scalar assertions

Create new assert_all_files_exist and assert_all_directories_exist functions

I know that its tempting to just name these assert_files_exist and assert_directories_exist but the all is part of our general naming rules for vectorised functions, so will the API more consistent. See #15 for details

Add system for evaluating coverage of created assertions

see #26 for context.

We should build

  1. utilities for extracting the names of all assertion functions in our codebase
  2. utilities for counting the number of unit tests (i.e. expect_ statements that test each assertion)
  3. a system that produces a badge describing (proportion of assertions with > some_threshold unit tests)

Some potential options for badges here:
basically we just need to produce a json file somewhere in this repo that we could point to.

https://css-tricks.com/adding-custom-github-badges-to-your-repo/

fix test fail for windows (assert_permission unit test)

Test failed:
'C:\Users\RUNNER~1\AppData\Local\Temp\RtmpmItq67/working_dir\RtmpcBAB6t\file1dcd4d59fc' does not have permission: execute

I think this is because of the colon. Just need to add it to our regex as a valid path character

add more badges

Number of issues resolved

  • code size
  • Number of issues closed
  • Last Commit Date

Release assertions 0.1.0

First release:

Prepare for release:

  • git pull
  • Check if any deprecation processes should be advanced, as described in Gradual deprecation
  • devtools::build_readme()
  • urlchecker::url_check()
  • devtools::check(remote = TRUE, manual = TRUE)
  • devtools::check_win_devel()
  • rhub::check_for_cran()
  • git push
  • Draft blog post

Submit to CRAN:

  • usethis::use_version('minor')
  • devtools::submit_cran()
  • Approve email

Wait for CRAN...

  • Accepted ๐ŸŽ‰
  • git push
  • usethis::use_github_release()
  • usethis::use_dev_version()
  • usethis::use_news_md()
  • git push
  • Finish blog post
  • Tweet
  • Add link to blog post in pkgdown news menu

Error message strings should have access to the values of the error function

#20 solution works so well for user-suppled msg's, lets try and add a similar solution for assert_create

default_error_msg AND func -defined error messages should have access to the environment of func

The code below SHOULD ideally work, but it doesn't, because the cli_abort environment is NOT the function(mutation_types) environment.

assert_all_mutations_are_valid_so <- assertions::assert_create(
  func = function(mutation_types) {
    unique_mutation_types <- unique(unlist(strsplit(mutation_types, split = "&")))
    unknown_mutation_types <- unique_mutation_types[!unique_mutation_types %in% mutation_types_so()]
    if(length(unique_mutation_types) > 0 ){
      "Found {.strong {length(unknown_mutation_types)}} mutation type{?s} which {?was/were} NOT valid SO terms: [{.strong {unknown_mutation_types}}]"
    }}
)

Lets forget about 'arg_name' and 'arg_value' and just let the user build error messages in the way that makes the most sense naturally

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.