Symfony’s Panther: Unleash the Tests Beast
End-to-end tests are going savagely easy
Testing an application isn’t the easiest thing on earth, it is not the quickest thing either and it may not be the most exciting part of an application development. But that’s just a necessary thing. You can’t take the risk of making your application crash and loose users — and maybe money at the same time. You got to be relaxed when pushing new code edits to your production. Tests exist for this reason and check the non-regression of your application. If your tests pass (and you wrote good tests, which is another whole and huge topic), you’ll be way more confident about sending new features and bugfix to your production without the fear of breaking everything.
We can roughly find three main types of tests when creating application:
1. Unit tests, which consists in testing little snippets of codes, like functions or maybe classes. It doesn’t involve anything more than the executed code and you mock external dependencies like the database by creating fake datasets (in the test code for example) just for those tests. They are really fast to execute ;
2. Functional tests, which test in general a feature in its globality, without having to worry on how things are done internally. A common use case of functional tests is API testing: you check that by calling a specific API URL with specific arguments, you’ll have a determined response from it. They have generally external dependencies with a database running. That’s why they can be sometimes a bit slow to execute, and most of the time way slower than unit tests ;
It is alway a matter of compromises: do you prefer to write tests super quickly but that only assure some code parts are fully working, or long and heavy tests that check a whole workflow and user path and that all buttons are at the right place? There is no good answer to this question and it is often a mix of these three ones.
So, what is actually Panther?
Symfony’s Panther belongs to the third category of tests. Created by Kévin Dunglas, with its version 1.0 released in February 2021, Panther is a standalone library to do end-to-end testing. Even if the library is described as “a browser testing and web scraping library for PHP and Symfony”, you can use it smoothly within any PHP application.
It’s syntax looks a lot like unit testing with PHPUnit. First good point: if you’re accustomed to write unit tests with PHPUnit, you won’t be out of place. If you want a bit more about exciting features Panther is capable of, here are a few directly taken from Panther’s Github:
- Take screenshots whenever you want and need, which is a must when setting up a CI or writing tests ;
- Ability to wait for asynchronously loaded elements ;
- All latest innovations embedded in Chrome and Firefox will always be present in Panther.
Just a few words on the last point. How is it possible? Well, the World Wide Web Consortium (W3C) is currently working on a standardized interface called WebDriver, to allow web browser to be automated and remote-controlled. As it is going to be a web standard, we’ll see more and more web browser supporting this interface in the future. Chrome and Firefox already implement this interface, which allows Panther to use full features of them.
What are its features?
As said earlier, if you’re familiar with PHPUnit tests, you’re pretty good, as it is the same syntax. Same story if you already did functional tests thanks to Symfony and its WebTestCases. The syntax is exactly the same. The reason is simple: Panther is an extension to PHPUnit and defined a PantherTestCase to expose some new assertions especially built for the occasion. “Classic” PHPUnit assertions are obviously still available. Among those new ones, we’ll find some to:
- Assert the page title ;
- Assert a selector exists, is enabled, contains something, is visible ;
- Assert attributes ;
- Wait for a node to be visible or not ;
- Wait for a node to have a certain attribute or content value ;
- And many more!
Dozens are available. So yeah, asserting is great, but interacting with the page is also super cool. Panther allows you to easily:
- Fill in and submit forms ;
- Click on links ;
- Take a screenshot in one line of code ;
- Access browser’s console ;
- And many more, again!
How does it look like?
To show you the look-and-feel of Panther and how to use it, here is a code snippet (a bit cleaned) for the documentation:
Don’t you have the impression we’re doing unit tests here? I personally love it. No need to learn a new syntax or language to create end-to-end tests if you’re used to PHP unit tests.
Internally, Panther itself will start a PHP server to execute the test. But that’s not mandatory thing, as you can pass to Panther an external base URI if you want to. This way, the internal PHP server won’t be started.
Even if the library is limited on some points, Panther is offering a fresh, clean and efficient way to create end-to-end tests in any PHP application. The documentation on the Github page of it is really complete and will help you to go further. What I mean is you’ll get complete examples on how to include it in your CI, with snippets for Github Actions, Travis, Gitlab and AppVeyor. You’ll also find everything you need about integrating Panther in a Docker container.
Another amazing feature to finish this article? It is fully compatible and designed to work with real-time technologies like Mercure and WebSockets!