PHP 8.1.0 RC 4 available for testing – PHP: Hypertext Preprocessor

The PHP team is pleased to announce the release of PHP 8.1.0, RC 4. This is the fourth release candidate, continuing the PHP 8.1 release cycle, the rough outline of which is specified in the PHP Wiki. For source downloads of PHP 8.1.0, RC 4 please visit the download page. Please carefully test this version and report any issues found in the bug reporting system. Please DO NOT use this version in production, it is an early test version. For more information on the new features and other changes, you can read the NEWS file or the UPGRADING file for a complete list of upgrading notes. These files can also be found in the release archive. The next release will be the fifth release candidate (RC 5), planned for 28 October 2021. The signatures for the release can be found in the manifest or on the QA site. Thank you for helping us make PHP better.

Ep#363 – Interview with Mike Stowe – Voices of the ElePHPant

Listen as host Khayrattee Wasseem talks with Mike Stowe. This is thorough explanation of the role of a developer marketing – the why, the how, the responsibilities, how not to cross boundaries and specially how to transition from dev to dev rel, including difference between Developer Evangelist, Developer Relations, Developer Advocacy & Developer Marketing.

This episode is sponsored by
RingCentral Developers

The post Ep#363 – Interview with Mike Stowe appeared first on Voices of the ElePHPant.

PHP 8.1.0 RC 3 available for testing – PHP: Hypertext Preprocessor

The PHP team is pleased to announce the release of PHP 8.1.0, RC 3. This is the third release candidate, continuing the PHP 8.1 release cycle, the rough outline of which is specified in the PHP Wiki. For source downloads of PHP 8.1.0, RC 3 please visit the download page. Please carefully test this version and report any issues found in the bug reporting system. Please DO NOT use this version in production, it is an early test version. For more information on the new features and other changes, you can read the NEWS file or the UPGRADING file for a complete list of upgrading notes. These files can also be found in the release archive. The next release will be the fourth release candidate (RC 4), planned for 14 October 2021. The signatures for the release can be found in the manifest or on the QA site. Thank you for helping us make PHP better.

Ep#362 – Interview with Derick Rethans – Voices of the ElePHPant

Listen as host Khayrattee Wasseem talks with Derick Rethans – indepth xdebug & xdebug Cloud discussion, his role as Release Manager for PHP 7.4, feature freeze, his creative side and the rapid-fire round.

This episode is sponsored by
RingCentral Developers

The post Ep#362 – Interview with Derick Rethans appeared first on Voices of the ElePHPant.

Quick Testing Tips: One Class, One Test? – Matthias Noback

I’ve mentioned this several times without explaining: the rule that every class should have a test, or that every class method should have a test, does not make sense at all. Still, it’s a rule that many teams follow. Why? Maybe they used to have a #NoTest culture and they never want to go back to it, so they establish a rule that is easy to enforce. When reviewing you only have to check: does the class have a test? Okay, great. It’s a bad test? No problem, it is a test. I already explained why I think you need to make an effort to not just write any test, but to write good tests (see also: Testing Anything; Better Than Testing Nothing?). In this article I’d like to look closer at the numbers: one class – one test.

A Platonic concept of object-oriented programming

Some say there are in essence two types of thinking. One based on Plato, one based on Aristotle. This may not really be the case, but it’s an attractive thought. I find that in testing at least there is a similar distinction. The rule that every class should have a corresponding test class is a Platonic rule. It is similar to Plato’s ideal world, which is (roughly speaking) a universe of ideas on which our concrete reality is based. Given that a programming problem is also an idea, and that classes are ideas as well, the problems and their class-based solutions all live in that ideal world. The programmer’s job is to extract those classes from the world of ideas and turn them into code that we can run on our computers. All the classes we’ll ever need already exist, we only have to discover them. Once we have found such a class (eureka!) we know, because of our team rule, that we have to now also create a test class for it. Why? Because we are mere mortals, and in the process of bringing that perfect class from the immaterial realm into our computer, we make mistakes. The real class is less perfect than the ideal class.

Classes are arbitrary things

Why doesn’t all of this make sense? Because we don’t discover classes the way they are. We arbitrarily decide on a set of properties and methods (data and behavior) that we want to keep together. The size of a class changes over time: we extract a new class, or we extract a method, and we often do the opposite too: we let the data and behavior of one class be absorbed into another one, and so on. Why? Because we want to fix some code smells, or maybe we made a design mistake. We want to try a different design pattern, or we want to revert that decision.

If the size and shape of a class is arbitrary, how can we link the number of required tests to the number of classes?

This is a known problem for the testing school that follows the one class-one test rule. They have to decide: when I extract class B from class A, do I write new tests for class B? Maybe not, because B’s behavior is indirectly covered by the test we already have for class A. Maybe yes, because I can mock B and test A and B separately. The same reasoning goes for methods: do you test each method? What happens when you extract a new method (maybe in another class, maybe in the same class)? Do you write new tests because you have to follow the rules?

It’s clear that in practice this one class-one test rule needs a lot of re-evaluation, leading to lots of discussion in the team. Furthermore, it leads to demotivating testing practices, where you spend a lot of time changing tests, writing tests that are mock-heavy, or are otherwise too close to the implementation of the subject under test.

An Aristotelian alternative

What is the alternative? In my experience, it makes a lot more sense to follow an Aristotelian approach. Down-to-earth. What do we have in front of us? What are we working on? What kind of test does it need? Can we test this at a somewhat higher level of abstraction than this class we only accidentally use? We shouldn’t be focused on classes anyway, since they are just the way we write code as object-oriented programmers: classes are an implementation detail. What matters is the behavior of the application as a whole. What value does it provide to the user?

When we focus on the bigger picture, we can separate the essential from the accidental. If our test covers only the essential parts, we can leave all the accidental parts inside the black box. We can then freely change those parts and still have a working test, because the test didn’t focus on the details. I find this a very rewarding approach to testing. It’s not as demotivating, because you don’t spend a lot of time rewriting tests. As a bonus, these tests tell the bigger story, and help the reader understand what’s going on in the code, and for what reason. So they will serve as documentation too; future programmers won’t have to re-invent and reverse engineer all the business rules again.

Debugging PHP Applications at Web Summer Camp 2021 – Liip

With Covid-19, physical conferences stopped happening. I gave a talk at the virtual Symfony World conference in 2020. The virtual conference was an interesting experience and a well organised event. But I missed travelling to a foreign place and meeting people between talks and in the evening. Hence, I was absolutely thrilled to be invited to do a workshop at the Web Summer Camp in Croatia.

Web Summer Camp Croatia is a unique event. There are no regular presentations, only hands-on workshops. You see fewer different topics than at a typical conference, but get to deep dive in those instead. The participants who had time to stay an additional day were invited on a boat trip on the beautiful Mediterranean sea.

Debugging PHP Applications

In my debuggin strategies workshop, I used PHP for the examples, but most of the content is applicable to any programming language. Using lots of small exercises, I let the participants try various debugging strategies to locate the bugs I had hidden in the application. Among other things, we did exercises to

  • Understand exception messages and stack traces to locate a problem
  • Use logs to identify where the problem is
  • Use unit tests and a test coverage report to identify an issue
  • Use git bisect to find the commit that introduced a regression
  • Demonstration of step-by-step debugging with the PhpStorm IDE

I also showed the clean code principles as a way to avoid errors from being made. I presented defensive programming and other methods to improve error reporting when something does go wrong.

For the showcase examples, I used a simplistic Symfony application that imports CSV files into a database and shows a query result from that database on the home page. The application is super simple, so that the participants understand what is going on and can focus on the debugging technique of the exercise. Each exercise is a branch in that repository with some change to introduce the bug.

Hire Me 😉

If you are interested in providing a hands-on workshop for your team, please get in touch with me. Meeting on-site will bring the best value, as the workshop is highly interactive.

Quick Testing Tips: Write Unit Tests Like Scenarios – Matthias Noback

I’m a big fan of the BDD Books by Gáspár Nagy and Seb Rose, and I’ve read a lot about writing and improving scenarios, like Specification by Example by Gojko Adzic and Writing Great Specifications by Kamil Nicieja. I can recommend reading anything from Liz Keogh as well. Trying to apply their suggestions in my development work, I realized: specifications benefit from good writing. Writing benefits from good thinking. And so does design. Better writing, thinking, designing: this will make us do a better job at programming. Any effort put into these activities has a positive impact on the other areas, even on the code itself.

Unit tests vs automated scenarios

For instance, when you write a test in your favorite test runner (like PHPUnit), you’ll write code. You’ll focus on technology, and on implementation details (methods, classes, argument types, etc.):

$config = Mockery::mock(Config::class);
$config->shouldReceive('get') ->with('reroute_sms_to_email') ->andReturn('developers@org.nl'); $fallbackMailer = Mockery::mock(Mailer::class);
$fallbackMailer->shouldReceive('send') ->andReturnUsing(function (Mail $mail) { self::assertEquals('The message', $mail->plainTextBody()); self::assertEquals('SMS for 0612345678', $mail->subject()); }); $smsSender = new SmsSender($config, $fallbackMailer);
$smsSender->send('0612345678', 'The message');

It takes a lot of reading and interpreting before you even understand what’s going on here. When you write a scenario first, you can shift your focus to a higher abstraction level. It’ll be easier to introduce words from the business domain as well:

Given the system has been configured to reroute all SMS messages to the email address developers@org.nl
When the system sends an SMS
Then the SMS message will be sent as an email to developers@org.nl instead

When automating the scenario steps it will be natural to copy the words from the scenario into the code, establishing the holy grail of Domain-Driven Design – a Ubiquitous Language; without too much effort. And it’s definitely easier to understand, because you’re describing in simple words what you’re doing or are planning to do.

Most of the projects I’ve seen don’t use scenarios like this. They either write technology-focused scenarios, like this (or the equivalent using Browserkit, WebTestCase, etc.):

Given I am on "/welcome"
When I click "Submit"
Then I should see "Hi"

Or they don’t specify anything, but just test everything using PHPUnit.

Writing scenario-style unit tests

Although it may seem like having any kind of test is already better than having no tests at all, if you’re making an effort to test your code, I think your test deserves to be of a high quality. When aiming high, it’ll be smart to take advantage of the vast knowledge base from the scenario-writing community. As an example, I’ve been trying to import a number of style rules for scenarios into PHPUnit tests. The result is that those tests now become more useful for the (future) reader. They describe what’s going on, instead of just showing which methods will be called, what data will be passed, and what the result of that is. You can use simple tricks like:

  1. Givens should be in the past tense
  2. Whens should be in the present tense
  3. Thens should be in the future tense (often using “should” or “will”)

But what if you don’t want to use Behat or another tool that supports Gherkin (the formalized language for these scenarios)? The cool thing is, you can use “scenario language” in any test, also in unit tests. The trick is to just use comments. This is the unit test above rewritten with this approach:

// Given the system has been configured to reroute all SMS messages to the email address developers@org.nl
$config = Mockery::mock(Config::class);
$config->shouldReceive('get') ->with('reroute_sms_to_email') ->andReturn('developers@org.nl'); // When the system sends an SMS
$fallbackMailer = Mockery::spy(Mailer::class);
$smsSender = new SmsSender($config, $fallbackMailer);
$smsSender->send('0612345678', 'The message'); // Then the SMS message will be sent as an email to developers@org.nl instead
$fallbackMailer->shouldHaveReceived('send') ->with(function (Mail $mail) { self::assertEquals('The message', $mail->plainTextBody()); self

Truncated by Planet PHP, read more at the original (another 3134 bytes)