Kuba @kuba.zalas.pl · 09/06/2026Ugh... you say this, my cheeky clanker, but you're gonna do it again, aren't you? 340
Kuba @kuba.zalas.pl · 25/02/2026I didn't use to clearly show hexagonal architecture in my folder structure, but reading the book by Alistair & Juan convinced me to start doing this. 010
Kuba @kuba.zalas.pl · 25/02/2026A good start overall. I'll continue with the approach and see where it takes me. 000
Kuba @kuba.zalas.pl · 25/02/2026Junie tough, didn't communicate what it was planning to do accurately. For example, it told me it's going to remove most of my settings.gradle.kts. It mislead me into thinking it wasn't listening to instructions. 210
Kuba @kuba.zalas.pl · 25/02/2026I got excellent results with AI Assistant. It decomposed the steps exactly the way I expected it to. 110
Kuba @kuba.zalas.pl · 25/02/2026I use tools available in @intellijidea.com, so I started by giving AI Assistant hints where to look for documentation by defining my first rule in .aiassistant/rules/README.md. 100
Kuba @kuba.zalas.pl · 07/08/2025Shared understanding. "Shared documents aren’t shared understanding." "Shared understanding is when we both understand what the other person is imagining and why." 100
Kuba @kuba.zalas.pl · 17/07/2025xUnit Test Patterns: Contract Test — zalas.pl/contract-test/ #contracttests #xunit #testing #hexagonal #portsandadapters #kotlin 101
Kuba @kuba.zalas.pl · 10/06/2025I like this reincarnation of the testing pyramid - the testing iceberg. It shows how not all business-readable tests need to be end-to-end, or even integrated. claysnow.co.uk/the-testing-... 020
Kuba @kuba.zalas.pl · 03/06/2025Thank you, @dev.to for the new badge, but I'd rather be able to save an article to update the canonical URL. What I get instead: Whoops, something went wrong: status: 500 error: Internal Server Error 010
Kuba @kuba.zalas.pl · 05/03/2025A healthy take on the test pyramid. “Eviscerating the Test Automation Pyramid” cucumber.io/blog/bdd/evi... 020
Kuba @kuba.zalas.pl · 20/02/2025Actors can have state. Since messages are processed one by one, state can be returned from actor's function to be passed with the next iteration. 100
Kuba @kuba.zalas.pl · 20/02/2025Inbox is a Mutable Shared Flow that you can emit messages to. Before returning the inbox, a new coroutine is launched to start processing incoming messages. 100
Kuba @kuba.zalas.pl · 20/02/2025Actors process messages that arrived in their inbox one at a time. The inbox reference is returned from `actorFor` in the example below. Each message emitted to the actor is passed to the actor's function. Below example just forwards messages to a Channel for further inspection. 100
Kuba @kuba.zalas.pl · 20/02/2025I'm playing with #Kotlin coroutines, channels and flow to reproduce actor-like behaviour. Yes, I know of the obsolete `CoroutineScope.actor`. Just playing! 100
Kuba @kuba.zalas.pl · 21/12/2024Yes, Ryanair, this is the perfect way to capture the date of birth. The older you're, the more annoying it becomes. #uxfail 250
Kuba @kuba.zalas.pl · 04/12/2024I’ve been an iPhone user since iPhone 6 replaced my Nexus 4 android phone in 2016. It then got replaced by iPhone 11 I have to this day. It’s time to try an Android phone again. I’m a bit worried I sit too deep in the Apple ecosystem. Let’s find out! 110
Kuba @kuba.zalas.pl · 26/11/2024I wonder how well AI assistants would do if we fed it with three volumes of "The Data Model Resource Book". 110
Kuba @kuba.zalas.pl · 23/11/2024“When we start to think and reason about a system with Events and Facts, it forces everybody to look at the system from a different perspective. We no longer think about data, columns and rows but behavior.” “Understanding Eventsourcing” By Martin Dilger 2195
Kuba @kuba.zalas.pl · 22/11/2024Some functional programmers like to divide code into three categories: data, calculations, actions. As we considered today, data needs no tests. Calculations have the most enjoyable tests to write. Actions is where the most problems are born. 130
Kuba @kuba.zalas.pl · 22/11/2024That leads us to the final type of behaviours I wanted to write about today. Behaviours that have other behaviours as their input or output providers. So-called indirect inputs and indirect outputs. 100
Kuba @kuba.zalas.pl · 22/11/2024That in turn requires the database to be started. It's easy enough these days with tools like Testcontainers. It is slow. It is fragile. It is necessary to verify the behaviour, though. 110
Kuba @kuba.zalas.pl · 22/11/2024Now there's no other way, but to populate that database, invoke the behaviour, and inspect the database again to see what has changed. 110
Kuba @kuba.zalas.pl · 22/11/2024Finally, both input and output can be provided by a call to the outside world (an I/O operation). A database, for example. 110
Kuba @kuba.zalas.pl · 22/11/2024Throwing an exception is an easy way out of the function, that interrupts the flow and jumps up the stack trace up to the point we catch it. Or not. Unless checked, exceptions are not part of the function signature. They come with a cost too. 110
Kuba @kuba.zalas.pl · 22/11/2024It's easy enough to verify. We need to capture it and verify it's the expected type or even a message. 100
Kuba @kuba.zalas.pl · 22/11/2024In isolation, the implementation might not look like it's going to cause us a headache, but considering the object could be accessed from anywhere, anyone can modify it. Mutable state isn't a problem. Shared mutable state is. 110
Kuba @kuba.zalas.pl · 22/11/2024We will need to either expose the internal state to inspect it, or find another way to verify it. Exposing the state often goes against the reason why we have it bundled with behaviour (encapsulation), but it's often easiest. 100
Kuba @kuba.zalas.pl · 22/11/2024If we make the state mutable, it can act as an additional output of the behaviour. Verification becomes awkward with mutable state, but it is possible. 110
Kuba @kuba.zalas.pl · 22/11/2024One other consequence of immutability is that the output has to be returned from the function. That means, we need to construct a new instance if the return type is the same as the object we're operating on. 110
Kuba @kuba.zalas.pl · 22/11/2024Since the state cannot be altered, the behaviour is still a calculation. It's just that some of the input is provided at the time of construction, rather than at the call time. 100
Kuba @kuba.zalas.pl · 22/11/2024Next, we can have behaviour attached to an immutable state. Think of a class with one or more properties and methods. The state can only be read, so it is an additional input to our behaviour. 110
Kuba @kuba.zalas.pl · 22/11/2024It's the most pleasant test to write as it tends to naturally follow the Arrange/Act/Assert, a.k.a. Given/When/Then. Given this input When I invoke this behaviour Then this the output I expect 100
Kuba @kuba.zalas.pl · 22/11/2024The simplest case are tests for calculations. Calculations have no side effects and, called with the same set of arguments, always return the same outcome. 110
Kuba @kuba.zalas.pl · 22/11/2024What is a behaviour? Behaviour can be defined by its input and its output. 110
Kuba @kuba.zalas.pl · 22/11/2024Let's start with data. How do we write a test for data? We don't. Data has no behaviour on its own. 100
Kuba @kuba.zalas.pl · 22/11/2024As software developers, we write #tests for behaviours exposed by systems we build. How to verify a behaviour? Let's consider a few examples in #kotlin 192
Kuba @kuba.zalas.pl · 15/11/2024Usage looks similar, but we now have an explicit representation of state. 110