How do you validate on a List (doesn't seem like t...
# akkurate
d
How do you validate on a List (doesn't seem like there's a section in the docs on this -- and it also seems that there's no specialized matchers list for this scope...)?
Copy code
val validateInstallActionList = dev.nesk.akkurate.Validator<List<InstallAction>> {
   // ....?        
}
(notice that Intellij had troubles importing
Validator
...?)
j
I should add a search bar to the documentation, it will help
👍🏼 1
And about the import, yeah I know... I have to report this. it happens when you already have the whole code already written:
Copy code
val validateInstallActionList = Validator<List<InstallAction>> {
   // ....?        
}
to force the import, put everything after
Validator
in comment:
Copy code
val validateInstallActionList = Validator /* <List<InstallAction>> {
   // ....?        
} */
then you will be able to use automatic import 😅
🤒 1
d
Oh, the support for lists is if there's a property in the class being validated that's an Iterable... my case wouldn't work (where I'm checking a List<InstallAction>...)
I guess since you don't use reified types, you would never know that type parameter anyways...
j
what is your use case? Could you demo what you want?
d
Basically testing the result of a UseCase in a microservice, which in this case is a ListInstallAction, and there might be contain, doesNotContain, containExactly, doesNotContainExactly, any, all, none, etc... but when checking the InstallAction, it only uses certain specified constraints, not just an == between expected and actual. I'm trying to use the ContextType as the actual...
I could maybe envision something like this:
Copy code
val validateInstallActionList = Validator<InstallAction> {
   // ....?        
}.forList()

validateInstallActionList.any(someResultList)

validateInstallActionList.contains(someResultList, expectedToHaveTheseEntries)

// etc...
j
Sorry I don't fully understand what you want to do. What kind of declaration is
InstallAction
? A sealed class/interface? An enum? Something else? What do you want to assert on this value? Its equality to something else?
or do you want to just run some custom constraint on some methods of
InstallAction
?
d
Just a regular data class... but the result I need to validate is a List<InstallAction>
j
OK, you want to validate the list (its size for example) or each element in it?
or both?
d
My original thought was really a bit of both, using the validations defined in different ways on the list is the main point.
any
would be any elements fulfill the criteria and would result in success. But now I'm rethinking things that in the context of ValidationResult what would be returned? It could be more practical to have some kind of result like Arrow's Ior.Both<Success.., Error...> in the case that some passed the validations and others didn't. That's moving away from the unit tests use case, but I agree that the main purpose of this library is validation and not assertions for unit tests... I'm still not sure how that would help in certain things in my case, though. But it might still be a good idea for the library.
j
yeah, test assertions and business validation aren't really the same things Here, Akkurate focuses (at least for now) on business validation, to ensure that what you store in your database is matching your business expectations. For this, it provides basic constraints on collections to check its size, and to apply constraints on each item of the collection. At the moment, there are no built-in way to do something like
any
. However, you can this manually by creating a custom constraint, but this is probably not what you're searching for.
d
I thought the
forList()
could maybe turn
Validator<InstallAction>
to some kind of
Validator.List<InstallAction>
which could have special constraints for lists, that could be done for Maps or even Iteration (to include sets). Wouldn't this maybe be useful in the validation context too? There's also lists coming from dbs... and validation failures could encompass multiple entries, and some might also have no problems... this could allow to return exactly what was wrong and what was right.
j
what type of constraints
Validator.List
would provide? Do you have some examples?
d
For now, the biggest use would be have a return type like Ior, to indicate which failed which succeeded or if all failed or all succeeded, that could already be useful... I guess right now I'm not in the validation context to be able to give more concrete constraints that might actually be useful in that context, but in the test assertions context there are certainly a few that come to mind... (for the
assertions
module...😉)
One potentially good validation could be if there's no duplicates in the list (maybe even by a particular property). This wouldn't be so practical for very large lists, but could come in handy to lay out certain expectations in smaller lists.
j
You already can know which item of a list fails the constraint:
Copy code
val validate = Validator<List<String>> {
    each { isNotEmpty() }
}

val strings = listOf("foo", "", "bar")
when (val result = validate(strings)) {
    is ValidationResult.Success -> TODO()
    is ValidationResult.Failure -> result.violations.forEach(::println)
}
It prints:
ConstraintViolation(message='Must not be empty', path=[1])
, you can see the path is a list containing
1
, then you know the second element did not match the constraint.
One potentially good validation could be if there's no duplicates in the list
Good idea! I was about to answer back "use a `Set`" but it might not be possible sometimes. I'm adding it to the roadmap 🙂