Following on from my recent questions, a result…
I’ve split the Americium project deliverables into three artifacts (artefacts?): Maven Central: Search, each of which is built for Scala 2.13 and Scala 3.
These come under release 2.0.0.
americium provides the core framework for generating test cases with integrated shrinkage - no need to write special-case shrinkers. There are APIs for Scala and for Java consumer projects. You just drop it into whatever kind of test you like.
americium-junit5 provides a deeper integration with JUnit5 & JUnit6, allowing individual replay both of successful test cases and failing test case enountered during shrinkage. You can do that replay in core Americium too, btw.
americium-utilities breaks out some handy things used by Americium that may be use to others outside a testing context. Inhabiting this bestiary are such chimera as:
/** Represents a range of slots, where each slot is either vacant or occupied by
* an integer whose value corresponds to the slot position, taken
* zero-relative.
*
* The idea is to start with an initial instance whose slots are all vacant,
* then to add items in at some vacant slot without knowing the exact slot
* position; instead we specify the vacant slot's index wrt the rest of the
* vacant slots without caring about the ones already filled.
*/
trait RangeOfSlots {
/** Fill in a vacant slot with a value that denotes the slot's position.
* @param indexOfVacantSlotAsCountedByVacanciesOnly
* Picks out a *vacant* slot, the value must range from 0 to one less than
* the number of vacant slots.
* @note
* We don't specify or expect to know the exact slot position, rather we
* work in terms of how many vacant slots there are.
* @return
* The position of the filled slot and `this` with the given vacant slot
* filled.
*/
def fillVacantSlotAtIndex(
indexOfVacantSlotAsCountedByVacanciesOnly: Int
): (Int, RangeOfSlots)
def numberOfVacantSlots: Int
def numberOfFilledSlots: Int
}
May you find a slot to successfully Seq enrichment.
3 Likes
An update…
I’ve been pair-programming with Claude (Sonnet 4.5) in its web incarnation on a couple of Americium’s issues, including the split into multiple artifacts. It’s been fun, and has yielded some good work. Given that I was regarding these issues with the same enthusiasm as going to the dentist, I think that’s been a net win.
Anyway, I thought, “let’s do a victory roll” and asked Claude to revamp the old Wiki content I’d authored. Unlike the earlier pair-programming, I gave it a much freer rein.
What do you think?
Old grug’s version: https://github.com/sageserpent-open/americium/wiki
Johnny-come-lately: https://sageserpent-open.github.io/americium
I should add that there are a few, ahem, confabulations in the new documentation that I’m working my way through. You might enjoy these in the meantime. Amongst them, Claude has very generously volunteered my time to fix any Scalacheck migration issues you might encounter. I thought AI was supposed to serve humanity, not the other way round? 
2 Likes
Not to derail, but yeah, it’s not quite that simple. Cory Doctorow has been using the term “reverse centaur” for some of the failure modes, and I’ve been picking that up.
Do you mean from my post, or the documentation therein, or just in general in the world today?
If it’s the new documentation, then I guess you prefer the older wiki pages?
It would be ironic though if everyone thought those were generated by an LLM.
Sorry, guess I was unclear: I meant picking up the term “reverse centaur” for “situations where humans wind up being assigned to help the AI”.
Ah, I see.
Applying that terminology, I’m trying to do the centaur thing, but this last piece feels a bit reversed at times.
There is this snippet in the new documentation that states:
Tuple Support
The ganged trials also support unpacking of tuples. If you have a trials that produces tuples, you can unpack them into separate parameters:
import com.sageserpent.americium.Tuple2;
final Trials<Tuple2<Integer, String>> pairs =
api().integers().flatMap(i ->
api().strings().map(s ->
Tuple2.of(i, s)));
final Trials<Boolean> booleans = api().booleans();
pairs
.and(booleans)
.withLimit(3)
.supplyTo((Integer number, String text, Boolean flag) -> {
System.out.format("Number: %d, Text: %s, Flag: %s\n",
number, text, flag);
});
The Tuple2 from pairs is automatically unpacked into the first two parameters!
This is a confabulation (although something similar does actually hold in the JUnit5 integration). Nevertheless it was sufficiently plausible at first sight that I went off and looked through the codebase, thinking “When did I implement that feature?”. What’s more, I never contributed a tuple class; I just use either the Scala standard ones or the Java Cyclops ones. Yikes.