RSS Amplifier

Blog

Software Development, Testing & Open Source

Technical articles and columns by Sebastian Bergmann

phpunit.expertRSS feed ↗74 posts

Latest posts

A language has non-functional requirements, too

Nobody decides whether a language is modern. What gets decided is whether you can bet a decade on it: who owns it, how upgrades arrive, how it scales, and whether you can still hire for it in year six. This article holds PHP to the criteria an architecture decision is actually made on.

Four out of five

How does PHP in 2026 compare with the current ideas about designing modern languages? This article takes stock of the criteria of closures, objects, pattern matching, generics, and an unconventional answer to the question of extensibility.

Your composer.lock knows what a carmaker only guesses

A car manufacturer lists an Android botnet in its open source attribution. The entry gives away how the list was made: by scanning instead of by declaring. Why a declared dependency list is worth more than a scanned one, and how the PHPUnit PHAR discloses its own contents.

When static analysis runs your code

A security vulnerability in PHPCSUtils revealed an eval() call in a static analysis tool. Why disable_functions cannot reach eval(), and what a switch in the PHP engine to disable it could look like.

Untouched tests are half the proof

My favourite kind of bug fix only adds a new regression test and leaves every existing test untouched. I checked this claim against PHPUnit's own history: I learned the most from the counterexamples.

Composer and Packagist under supply chain stress

2025 and 2026 proved to be a stress test for the supply chains of all package ecosystems. A review of Composer and Packagist: what PHP does well, what it can learn — and who owns our infrastructure.

Stories about systems that resist people

Five of the best television series I have ever seen are about the gap between what people want to achieve and what institutions allow them. They fascinate me because, after decades of developing Open Source software, I know much of this from my own working life.

Precision and Clarity: What is new in PHPUnit 13.2?

Selecting exactly the tests you want, finer control over the order they run in, faster and clearer output when they fail, and more expressive test doubles: I walk you through what is new in PHPUnit 13.2.

Merging code coverage data

Merging code coverage data from parallel CI jobs has long been fragile and error-prone. These problems are finally solved.

What your test run already knows

On every run, PHPUnit knows how long each test took, how much memory it used, and why it failed. Most of that evaporates. otr-report reads it back out of the Open Test Reporting logfile and puts it within reach.

Speed as a security feature

How fast is your test suite, and what vulnerabilities does an LLM agent therefore fail to detect? What was long considered a productivity issue is now part of the security debate.

Turbo-Charging Your PHPUnit Suite

Slow tests destroy flow, kill TDD, and erode trust until nobody runs the suite. The fix has four tiers, and the biggest wins come from test design, not from infrastructure or parallelisation.

Test-Driven Security

For every vulnerability we find in production, there is a test that, had it existed, would have prevented it. Test-Driven Security treats the CWE list as a checklist and PHPUnit as the tool we already have in our workflow.

Debugging as a design goal

Why do some bugs feel like a short detective story, while others feel like a never-ending thriller? I show you which decisions make your software debuggable.

Code I do not have does not cause any problems

Not every problem requires new code. And every line we do not write is a line that will not cause any problems.

The attack surface begins in the repository

We protect what exists. But do we ask often enough whether it should exist at all? How removing unused branches can protect against Poisoned Pipeline Execution.

Hardening GitHub Actions workflows

A walk through the GitHub Actions weaknesses in PHPUnit's workflows, how each one could have been exploited, and what was changed to close them.

ComoCamp 2026

Three days in Vienna, three days of ComoCamp: my report on inspiring workshops, exciting open space sessions, and the uniquely open, collaborative atmosphere.

Closures, Clarity, and Control: What is New in PHPUnit 13.1?

Closures as data providers, richer Open Test Reporting, custom issue trigger resolvers, and significant changes to code coverage: I walk you through the changes.

Technical debt is not malice

Technical debt is not malice, it is context. An argument for why empathy is a technical skill that matters more than you think.

Debugging Performance in PHP

"It feels slow" is not a diagnosis. I explain the three disciplines that turn vague complaints into actionable data: tracing, profiling, and benchmarking.

The Bouncer in the Dependency Resolver

Composer 2.9 moved security advisory enforcement from an opt-in third-party package into the resolver itself. This article walks through how the mechanism works, how it relates to the older packages it replaces, and where it can bite you.

Everything we have

In a world with endless possibilities for code to be wrong, one approach alone is not enough to make our software truly robust.

Security through chaos

This practical deep dive into the philosophy behind "security through chaos" shows that security does not come from perfect foresight, but from surviving chaos.

Beyond Best Practices

Testing, code reviews and documentation are all essential prerequisites that constrain the autonomy of AI, thereby safeguarding human agency in software development.

Effective Code Reviews

Pair, pull, or post-push? Find the code review strategy that is right for your team.

Faster than understanding

An AI coding agent implemented a complex software metric in 15 minutes. I have now spent hours trying to figure out whether the implementation is correct. Is this really a productivity boost?

From anti-pattern to clarity

The any() matcher is deprecated. But migration is easier than you think – and leads to better tests.

Better than withConsecutive()

I explain how PHPUnit 13's parameter set matchers finally solve the problem that made upgrading to PHPUnit 10 such a challenge.

Replay Testing

Replay Testing leverages the memory of your event sourcing system to test new versions with real history and shows which oracles truly inspire confidence in your changes.

From Events to Insights

Event Storming, DDD, CQRS, and Event Sourcing are intertwined: the tests not only check the events, but also become living documentation and a bridge between technical expertise and code.

How my understanding of software changed

A classic database only stores the "now" and forgets history. In this article, I describe my journey to DDD and event sourcing and explain why we need to learn to model time itself.

Data Provider or Properties?

One test, hundreds of inputs, and an automatic edge case search. But property-based testing has a hidden pitfall that many overlook.

Smaller input, greater insight

Shrinking is the unsung hero of property-based testing. I show you how it helps to make inevitable errors understandable.

Property-Based Testing

We only test what we think of. That is precisely what can become a problem.

Open Source, Open Feeds: Mastodon and PeerTube as online spaces for the PHP community

With phpc.social and phpc.tv, the PHP community is building its own donation-funded online spaces in the Fediverse – free from algorithms and fascist tech bros.

Type-Safe Collections

Does PHP really need generics? A controversial thesis with a practical solution.

How PHP and its ecosystem test each other

PHP tests Laravel, Symfony, PHPUnit, and more every night. PHPUnit tests PHP. This is Open Source collaboration at work.

The Stub/Mock Intervention

Self-sabotaging mock objects? With PHPUnit 12.5, that's a thing of the past because the test runner now asks the right question: Do you really need a mock object, or would a test stub suffice?

A festive break

I take a break from my weekly articles and invite you to a free online event where I will present the latest improvements to PHPUnit.

A flight recorder for your code

Your PHP project has no tests and an upgrade is pending? The classic dilemma: to introduce tests, you have to change code – to change code, you need tests. How can you break this cycle? With characterisation tests.

Seeing the Truth: Test Oracles

Your tests are successful. But are they really? Without a suitable test oracle, you will never know.

Testing with DTOs and Value Objects

Know the differences between data transfer objects and value objects and understand why immutability helps with testing.

Testing with(out) dependencies

Why distinguishing between test stubs and mock objects in PHPUnit significantly improves the quality and readability of tests.

Path Coverage or Mutation Testing?

How thoroughly do your tests cover the code, and how reliably do they detect real errors? I show you how to find out.

Open Source Blackout

Are you prepared for a world in which your projects freeze, deployments stall, and tech giants can no longer rely on free community-run infrastructure?

More control, less friction: What's new in PHPUnit 12.4?

Discover how PHPUnit 12.4 helps you get there with less friction and more insight.

Modern PHP Development

Modern PHP development combines proven principles with the latest tools. It brings together documentation, quality, automation, and AI.

A look ahead to 2035

I discuss key issues for the future relating to ethics, digital sovereignty, Open Source, and web standards.

PHPUnit features that surprise even professionals

Discover the hidden capabilities of PHPUnit and learn how to get the most out of your tests with clever features.