As Joomla 4 is on the horizon, extension developers have to make their products available on two different major versions. So testing your extension becomes even more important. Instead of doing it manually with your components, modules or plugins, it is much more convenient to make that process automated and repeatable. In this blog post you will learn why it's time now to start with automated system testing.
When you have an extension which works on Joomla 3, it doesn't mean it will on 4 as well out of the box. Some deprecated functionality got removed in Joomla 4 and some things are new like the Bootstrap 5 lift. When you start now to test your extension on Joomla 4, it would be a good time to setup an environment which does the testing for you in an automated way. That's where system testing comes up on the table. In Joomla core we are using system testing already since years, but in the extension developers land it is still rarely seen. Time to change this!
Why not Unit testing?
Unit testing is the defacto standard when you build any kind of software project, not only with PHP. Unfortunately Joomla has a very bad architecture for proper unit testing and the testing team of Joomla is doing its best to improve this situation. As we extension developers build our stuff on top of the core we suffer from this as well. In Jooma 4 things do improve, but is still not close to an architecture for state of the art Unit testing. The biggest problem is that a lot of static factories and helper classes are used across the whole code base instead of injecting the dependencies. So we have to do a lot of workarounds to get our units tested the way it should. If you look on this presentation, then you will see that you can't do isolated unit testing, a lot of setup work is needed, especially with the application god object. That's why we switched to system testing and skip Unit testing for our Joomla extensions at Digital Peak.
Setup
Setting up an environment for automated testing is a rather complex task as a lot of different applications must be set up and configured correctly to play nicely together. The apps are, Codeception for writing the system tests, selenium as connector to the browser and a web server. The official Joomla documentation contains an extensive chapter how to setup system testing for extensions, it will help you to understand the whole process better. It this chapter we touch only the surface in terms of set up stuff as later we explain DPDocker which does all the heavy work for us.
Codeception
Codeception is a library which allows developers to write system tests in a simple but powerful way. You can do tons of different interactions with a web page directly in PHP like a right click or executing some Javascript. The following example shows you how such a test looks like in a Joomla context:
public function seeNativeEventsInList(Event $I, Menu $IM) { $I->wantToTest('that native events are displayed in the list view.'); $event = $I->createEvent(); $menuItemId = $IM->createListMenuItem(); $I->doFrontEndLogin(); $I->amOnPage(ListPage::$url . '&Itemid=' . $menuItemId); $I->click('Edit'); $I->fillField('#jform_title', 'Demo title'); $I->click('Save & close'); $I->see('Demo title'); }
The codeception getting started guide has some good examples to get you up and running in minutes. In your dev dependencies it is recommended to also include the joomla browser, which offers some helper functions to interact with a Joomla based web site.
Selenium and a browser
Selenium is the bridge between your PHP tests and the browser. It offers an API to interact with a browser of choice. Basically it starts a web server where apps can execute commands which will then tell a browser to do certain tasks. The following quote is from their docs:
Selenium is an umbrella project for a range of tools and libraries that enable and support the automation of web browsers.
Setting up Selenium is a bit more challenging as you need to have Java installed, but the web is full of resources which will help you to get it up and running.
Web server
What you need to have available is a running web server with a joomla installation. This web server needs a blank Joomla installation and depending on your codeception setup you can either install your extension during the system tests or install it upfront.
Docker to the rescue
All of this sounds complicated and it is indeed. As our founder Allon Moritz get in touch the first time with system testing at JandBeyond 2016 in Barcelona, it was very time consuming to setup all of this on a local computer. Since then a lot has changed and for almost everything is a docker container available nowadays. So you don't have to mess with dependencies on your local computer anymore.
We at Digital Peak went one step further and created a project for us inhouse, where we made a reusable docker environment to test our different extensions. As some more developers brought up their interest in this, we open sourced the whole project with the name DPDocker. You can find the sources and documentation on github. Basically it takes away the tasks to setup Joomla, install the extension, start selenium, mysql and configure/run codeception.
If you want to have an example, download the DPAttachments extension into the same folder as you have DPDocker and browse around the tests folder.
Requirements
Docker file operations have the best performance on Linux computers, so it is recommended to work on one of the different distros out there like Ubuntu. You can download DPDocker somewhere into a folder on your computer where you have your Joomla extensions located. Then install the docker and docker compose binaries. That's it. Now you are ready to go.
The extension needs a tests folder with an acceptance folder in it, this is the location for your tests. Additionally, you need a "_bootstrap.php" file in the tests folder and in the tests/acceptance folder. There you can do some setup stuff which will be executed before codeception is running the tests. Like including some base classes or defining some global variables like a timeout.
Test your setup
Basically your extension needs to have a specific folder structure, either have all of them in the root folder of your project or in the structure of a normal Joomla installation. We wil give you an example:
PackageFoo:
- com_foo
- mod_foo
- plg_content_foo
or
PackageFoo:
- administrator
- components
- com_foo
- components
- com_foo
- modules
- mod_foo
- plugins
- content
- foo
A simple test to see if docker works with DPDocker and if your extensions are automatically installed is when you start the web server with the following command:
DPDocker/webserver/run.sh
It starts a web server with Joomla 3 and 4 installed and the extensions which are in the same folder as the DPDocker project linked into it. More information about the installation process is described in the DPDocker project. The startup takes a while the first time as it installs a couple of different joomla installations. At the end you can open the browser and you should see on localhost/j3 a joomla site with your extensions linked into it.
Write your first test
If you have DPDocker running, then it's time to write your first test. Create a file with the name FrontpageCest.php in the folder tests/acceptance of your extension project with the following content:
class FrontpageCest { public function canSeeFrontPage(\AcceptanceTester $I) { $I->wantToTest('that the frontpage opens correctly.'); $I->amOnPage('index.php'); $I->waitForElement('.com_content'); $I->see('Home'); } }
Then start the system tests with the following command:
DPDocker/tests/run-system-tests.sh PackageFoo
It takes a while as Joomla 3 and 4 needs to be installed first (building the Joomla 4 assets is the time consuming part). Then you should see an output that codeception is starting and executing your test. First on Joomla 3 and then on Joomla 4. At the end a screen like the following one should be visible.
Conclusion
We touched here only the surface, but you can see that automated system testing gives you a powerful way to test your Joomla extension. We at Digital Peak do not merge a bug fix or feature without a system test anymore. Like that we can ensure that the bug will never appear again and that new features work the way we expect them.
We even went one step further and have automated our documentation screenshots. Like that we can recreate the screenshots on every Joomla or extension release and they will fit always the most actual version. Basically every repetitive work in our development process like uploading the documentation, creating releases or building the assets is made as a docker task. Like that the devs do not have to mess around with dependencies and waste time for setup stuff. Hope you will see the benefits as well.