Skip to content

Commit

Permalink
Merge pull request #77 from ba-st/assertion_checker_improvements
Browse files Browse the repository at this point in the history
Let AssertionChecker as the entry point for using the library
  • Loading branch information
gcotelli authored Mar 16, 2023
2 parents b13c72c + 6c5bb38 commit 0c1847f
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 149 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/loading-groups.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
load-spec: [ deployment, dependent-sunit-extensions, tests, tools, development ]
name: ${{ matrix.smalltalk }} + ${{ matrix.load-spec }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: hpi-swa/setup-smalltalkCI@v1
with:
smalltalk-image: ${{ matrix.smalltalk }}
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
smalltalk: [ Pharo64-10, Pharo64-9.0, Pharo64-8.0, Pharo64-7.0, Pharo32-7.0 ]
name: ${{ matrix.smalltalk }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: hpi-swa/setup-smalltalkCI@v1
with:
smalltalk-image: ${{ matrix.smalltalk }}
Expand All @@ -23,3 +23,4 @@ jobs:
uses: codecov/codecov-action@v3
with:
name: Unit-Tests-${{matrix.smalltalk}}
token: ${{ secrets.CODECOV_TOKEN }}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Quick links
- Additional Math abstractions
- Bindings and Optionals
- Exception Handling extensions
- Metaprogramming
- Meta-programming
- SUnit extensions

## License
Expand Down
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ understanding over specific topics:
required values, that can be unknown at the beginning of an execution.
See the [related documentation.](reference/BindingsAndOptionals.md)
- **Exception Handling**: Extensions to the [exception handling mechanics](reference/ExceptionHandling.md).
- **Metaprogramming**: Some abstractions like [namespaces](reference/Namespaces.md)
- **Meta-programming**: Some abstractions like [namespaces](reference/Namespaces.md)
and [interfaces](reference/Interfaces.md).
- **SUnit**: [Extensions to the SUnit framework](reference/SUnit.md).

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/Collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ iterator next "$b".

## Ordered Set

An `OrderderSet` is a set preserving the element's insertion order. It complies
An `OrderedSet` is a set preserving the element's insertion order. It complies
with the sequenceable collection protocol.

```smalltalk
Expand Down
4 changes: 2 additions & 2 deletions docs/reference/Comparison.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ It will apply the combinator operator to each one of the objects:
collection and then combine them.
- `combineHashOf:with:` will send the hash message to the two objects and then
combine them.
- `combineAll::` expectes a collection of hashes and will combine them.
- `combineAll::` expects a collection of hashes and will combine them.
- `combine:with:` will combine two hash values

### Hash Combinator Examples
Expand All @@ -42,7 +42,7 @@ Equality checkers always performs a `==` comparison first and proceed with the
rest of the rules only if the objects are not identical.

By default `equalityChecker` is an instance of `PropertyBasedEqualityChecker`
and it alredy knowns the receiving instance. It can be configured with:
and it already knowns the receiving instance. It can be configured with:

- `compare: selector` will add a rule to the checker that sends the provided
message on the receiver and target object and compare the results by `=`
Expand Down
71 changes: 33 additions & 38 deletions docs/tutorial/Assertions.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,42 +37,39 @@ a valid code consists only of letters. So let's rewrite our example:
code := 'AR'.
AssertionCheckerBuilder new
checking: [ :asserter |
AssertionChecker
check: [ :asserter |
asserter
enforce: [ code size = 2 ]
because: 'ISO 3166-1 Alpha-2 codes must have exactly two letters';
enforce: [ code allSatisfy: #isLetter ]
because: 'ISO 3166-1 Alpha-2 codes must only contain letters'
];
buildAndCheck
]
```

Note that in this case we are creating an `AssertionCheckerBuilder` and
configuring all the conditions to enforce. Let's try now replacing `code` with
`'AR3'` and `Do it` again. By default all the conditions to enforce are checked
so you should get an error message combining both explanations, and if you
handle the raised exception you can get all the failures by sending it the
message `failures`.
Note that in this case we are configuring all the conditions to enforce. Let's
try now replacing `code` with `'AR3'` and `Do it` again. By default all the
conditions to enforce are checked so you should get an error message combining
both explanations, and if you handle the raised exception you can get all the
failures by sending it the message `failures`.

If you want the more usual behavior of stopping after the first failure you can
configure the builder to fail fast:
configure it to fail fast:

```smalltalk
| code |
code := 'AR3'.
AssertionCheckerBuilder new
failFast;
checking: [ :asserter |
AssertionChecker
check: [ :asserter |
asserter
enforce: [ code size = 2 ]
because: 'ISO 3166-1 Alpha-2 codes must have exactly two letters';
enforce: [ code allSatisfy: #isLetter ]
because: 'ISO 3166-1 Alpha-2 codes must only contain letters'
];
buildAndCheck
]
configuredBy: [ :checker | checker failFast ]
```

If you `Do it` you will get only the first failure, the next conditions won't
Expand All @@ -90,19 +87,18 @@ valid code. Now we will consider only the officially assigned codes as valid:
code := 'AA'.
officiallyAssignedCodes := #('AR' 'BR' 'US').
AssertionCheckerBuilder new
checking: [ :asserter |
AssertionChecker
check: [ :asserter |
asserter
enforce: [ code size = 2 and: [ code allSatisfy: #isLetter ]]
because: 'ISO 3166-1 Alpha-2 codes must have exactly two letters'
onSuccess: [ :sucessAsserter |
sucessAsserter
onSuccess: [ :successAsserter |
successAsserter
enforce: [ officiallyAssignedCodes includes: code ]
because: [ '<1s> is not an officially assigned code'
expandMacrosWith: code ]
]
];
buildAndCheck
]
```

Here we are introducing two new features:
Expand All @@ -112,8 +108,7 @@ Here we are introducing two new features:
is satisfied. So we can make assumptions about what `code` looks like at this point.
- Second, using a block as the `because:` argument. This avoids creating
unnecessary objects because the explanation will only be evaluated if the
condition is not met. In this case the argument is a literal String, so it
makes no difference.
condition is not met.

## Refusing

Expand All @@ -126,26 +121,25 @@ Sometimes it's easier to explain a condition using negative logic, so
code := 'AR'.
unassignedCodes := #('LO' 'LP' 'OU').
AssertionCheckerBuilder new
checking: [ :asserter |
AssertionChecker
check: [ :asserter |
asserter
enforce: [ code size = 2 and: [ code allSatisfy: #isLetter ]]
because: 'ISO 3166-1 Alpha-2 codes must have exactly two letters'
onSuccess: [ :sucessAsserter |
sucessAsserter
onSuccess: [ :successAsserter |
successAsserter
refuse: [ unassignedCodes includes: code ]
because: [ '<1s> is an unassigned code' expandMacrosWith: code ]
]
];
buildAndCheck
]
```

## Configuring the error to raise

If not specified the library will raise `AssertionFailed` when some check fails.
If you want to raise a different kind of error there are two ways to configure it:

For single condition checks you can use `enforce:because:raising:` or `refuse:because:raising:`.
For single condition checks, use `enforce:because:raising:` or `refuse:because:raising:`

```smalltalk
| code |
Expand All @@ -158,24 +152,25 @@ AssertionChecker
raising: Error
```

When using the builder you should use:
For multiple condition checks, use:

```smalltalk
| code |
code := 'AR'.
AssertionCheckerBuilder new
raising: InstanceCreationFailed;
checking: [ :asserter |
AssertionChecker
check: [ :asserter |
asserter
enforce: [ code size = 2 ]
because: 'ISO 3166-1 Alpha-2 codes must have exactly two letters';
enforce: [ code allSatisfy: #isLetter ]
because: 'ISO 3166-1 Alpha-2 codes must only contain letters'
];
buildAndCheck
]
configuredBy: [ :checker |
checker raising: InstanceCreationFailed
]
```

but keep in mind when using the builder that the error to raise must understand
but keep in mind when using multiple conditions, that the error to raise must understand
`signalAll:` in order to work.
Loading

0 comments on commit 0c1847f

Please sign in to comment.