Asserting page load times in Magento with Magium

Leave a comment

Validating SLAs (Service Level Agreements) is often part of executing browser tests. With Magium you can now include page timings as part of your test. Say, for example, that part of your SLA is that a page must be rendered in less than 5 seconds. This is done by using the TTFBLoadedLessThan, DOMPageLoadedLessThan or DOMContentLoadedLessThan … Continue reading “Asserting page load times in Magento with Magium”

Powered by WPeMatico

Validating that page assets are cached

Leave a comment

It’s not just HTML elements that need to be tested, and sometimes not even testing that images or CSS files are being tested. Sometimes you need to test things like server configurations. Magium’s position is that there are a wealth of different areas where browser testing can benefit your organization. Validating browser testing configurations is … Continue reading “Validating that page assets are cached”

Powered by WPeMatico

Drawing floating columns/bars in Flot

Leave a comment

Let me say first of all, that I mostly like Flot as a charting application. It provides a lot of charting functionality and is reasonably good looking.

But sometimes it is a bit of a pain to deal with. Case in point; I wanted to create a chart that had floating columns (Flot, in my opinion incorrectly, calls vertical columns, bars). In essence, what I wanted was this:


Well, it can be done but, after I spent far too many hours trying to figure out how, it is not exactly clear how to do it.

The first thing I learned was that the data format for a bar is the opposite of what one would intuitively expect.  That doesn’t mean that it’s wrong (it make sense in retrospect), it’s just not intuitive.

If you want to float a bar/column in Flot you do it in the following format:

[[index, max, min]]

I had figured that min would come before max.  But that does not.

But that does not completely solve the problem because Flot does not allow you to control how the bottom bar is rendered; it is automatic.  And that automatic rendering removes the bottom border with no option to force it.  The result of the previous JavaScript array is:


That’s not horrible, but the lack of a bottom looks a little cheap.  The solution?  Create a second item in your dataset like this:

[[index, max, min]],
[[index, min, min]]

It feels a little dirty but it works.  You are creating a 1px border by putting another column with no height immediately below your column.  This is the result:


ChromeDriver hangs with Selenium Server and Xvfb

1 Comment

I have spent several hours working on an issue while running Selenium Server under Xvfb with ChromeDriver.  There would basically be a 30 second timeout when connecting to Selenium Server from WebDriver with this being the exception:

1) Tests\Magium\AbstractTestCase\CoreAssertionTest::testElementDisplayed
Facebook\WebDriver\Exception\WebDriverCurlException: Curl error thrown for http POST to /session with params: {"desiredCapabilities":{"browserName":"chrome","platform":"ANY"}}

Operation timed out after 30001 milliseconds with 0 out of -1 bytes received

/var/lib/jenkins/jobs/Magium (personal)/workspace/vendor/facebook/webdriver/lib/Exception/WebDriverException.php:89
/var/lib/jenkins/jobs/Magium (personal)/workspace/vendor/facebook/webdriver/lib/Remote/HttpCommandExecutor.php:254
/var/lib/jenkins/jobs/Magium (personal)/workspace/vendor/facebook/webdriver/lib/Remote/RemoteWebDriver.php:97
/var/lib/jenkins/jobs/Magium (personal)/workspace/lib/WebDriver/WebDriverFactory.php:17
/var/lib/jenkins/jobs/Magium (personal)/workspace/vendor/zendframework/zend-di/src/Di.php:547
/var/lib/jenkins/jobs/Magium (personal)/workspace/vendor/zendframework/zend-di/src/Di.php:321
/var/lib/jenkins/jobs/Magium (personal)/workspace/vendor/zendframework/zend-di/src/Di.php:265
/var/lib/jenkins/jobs/Magium (personal)/workspace/lib/TestCase/Initializer.php:53
/var/lib/jenkins/jobs/Magium (personal)/workspace/lib/AbstractTestCase.php:70

I strace()ed the process and it came down to a read() on a pipe sitting there, but I could not figure out why.  Eventually I worked my way into the temp directory for the hung process, /tmp/  In there is the file chrome_debug.log.   In that file was one entry:

[11259:11259:0412/] InitializeSandbox() called with multiple threads in process gpu-process

Searching Google, I came upon this discussion on GitHub.  The problem they noted was for Docker, and I wasn’t running Docker, but the problem was very similar.  The solution was to set the environment variable: DBUS_SESSION_BUS_ADDRESS=/dev/null.

I made the change to my systemd service file


ExecStart=/bin/java -Dselenium.LOGGER=/home/selenium/selenium.log -jar /var/www/selenium/bin/selenium-server-standalone-2.53.0.jar
ExecStop=kill `cat /var/spool/selenium/pid/`


I’ve run about 300 tests so far with no timeouts. Yay!

Browser Testing Twitter OAuth Accounts

Leave a comment

I added a Twitter OAuth integration in @magiumlib so you can easily do authentication automation.

— Kevin Schroeder (@kpschrade) April 6, 2016

This is a simple library to help browser tests perform OAuth logins to Twitter.

To install

composer require magium/twitter

To use:

use MagiumTwitterActionsAuthenticateTwitter;

class TwitterTest extends MagiumAbstractTestCase

    public function testLogin()
        // Do something that forwards the browser to the twitter OAuth page.

         $action = $this->getAction(AuthenticateTwitter::ACTION);
        /* @var $action AuthenticateTwitter */


Setting the username and password

There are two ways to set the username and password

In code

use MagiumTwitterIdentitiesTwitter
use MagiumTwitterActionsAuthenticateTwitter;

class TwitterTest extends MagiumAbstractTestCase

    public function testLogin()

        $identity = $this->getIdentity(Twitter::IDENTITY);
        /* @var $identity Twitter */

        // Do something that forwards the browser to the twitter OAuth page.

         $action = $this->getAction(AuthenticateTwitter::ACTION);
        /* @var $action AuthenticateTwitter */


In configuration

Create the file /configuration/Magium/Twitter/Identities/Twitter.php and enter the following:


/* @var $this MagiumTwitterIdentitiesTwitter */
$this->username = 'username';
$this->password = 'password';

Note that you should be familiar with AbstractConfigurableElements to do this

Not in Magium

This library doesn’t require Magium to run. Well, actually it does, but it doesn’t need the abstract test class. It’s a little verbose, but this is what it would look like (you could also use a DIC to manage this).


namespace TestsMagiumTwitter;

use FacebookWebDriverRemoteDesiredCapabilities;
use FacebookWebDriverRemoteRemoteWebDriver;
use FacebookWebDriverWebDriverBy;
use MagiumTwitterActionsAuthenticateTwitter;
use MagiumTwitterIdentitiesTwitter;
use MagiumUtilConfigurationClassConfigurationReader;
use MagiumUtilConfigurationConfigurationCollectorDefaultPropertyCollector;
use MagiumUtilConfigurationConfigurationReader;
use MagiumUtilConfigurationEnvironmentConfigurationReader;
use MagiumUtilConfigurationStandardConfigurationProvider;
use MagiumWebDriverExpectedCondition;
use MagiumWebDriverWebDriver;

class NoAbstractTestClassTest extends PHPUnit_Framework_TestCase

    public function testWithoutMagium()
        // Do some stuff to get to the Twitter authenticaation page

        // Start from here

        $configurationProvider = new StandardConfigurationProvider(
            new ConfigurationReader(),
            new ClassConfigurationReader(),
            new EnvironmentConfigurationReader()
        $collector = new DefaultPropertyCollector();

        $action = new AuthenticateTwitter(
            new MagiumTwitterThemesTwitter($configurationProvider, $collector),
            new MagiumTwitterIdentitiesTwitter($configurationProvider, $collector)

        // Everything up to here could have been done using a DIC.



Powered by WPeMatico

Logging in to the Magento Admin UI

Leave a comment

Logging in to the admin UI is fairly simple, but there are a few things you need to do ahead of time. The actual functionality looks like this:

class LoginTest extends MagiumMagentoAbstractMagentoTestCase

    public function testLogin()


That is all that is needed to log in… from the perspective of an action. But you do need to configure it to work in your environment. There are two ways of doing that.

The bad, but easy way

The easiest way is to configure your admin identity and theme directly in your test.

class LoginTest extends MagiumMagentoAbstractMagentoTestCase { public function testLogin() { $theme = $this->getTheme(MagiumMagentoThemesAdminThemeConfiguration::THEME); /* @var $theme MagiumMagentoThemesAdminThemeConfiguration */ $theme->set('baseUrl', 'http://localhost/admin/'); $admin = $this->getIdentity(MagiumMagentoIdentitiesAdmin::IDENTITY); /* @var $admin MagiumMagentoIdentitiesAdmin */ $admin->setAccount('myaccount'); $admin->setPassword('mypassword'); $this->getAction(MagiumMagentoActionsAdminLoginLogin::ACTION)->login(); } }

That will work, but what if something changes. Then you’ll need to go and change each and every instance where you did that. For that reason you should choose the

Marginally more complicated, but infinitely better way

This involves using the configurable nature of Magium. There are two files you will need to create in the base of your project.

  1. /configuration/Magium/Magento/Themes/Admin/ThemeConfiguration.php
  2. /configuration/Magium/Magento/Identities/Admin.php

This file will contain the configuration information for the theme. In this case the only thing we need to change is the baseUrl.


$this->baseUrl = 'http://magento19.loc/admin/';


Next up you will need to set the admin username and password.

$this->account = 'myaccount';
$this->password = 'mypassword';


From there any test that requires the admin will be automatically configured to work with these credentials and with this URL.

If you still need some help understanding configurable elements you should check out this video.

Powered by WPeMatico

Excluding fields in the mongodb/mongodb library

Leave a comment

I am using the mongodb/mongodb library for a project of mine.  The API seems fairly different from the old PECL library and it also came with some other, albeit unexpected, baggage.

My understanding of the library is that it is intended to be a replacement for the existing PECL library and that it intends to strike a balance between the core library functionality while also giving it a more agile, for lack of a better term, release cycle.  What that means is that there is some basic MongoDB functionality written in C with the forward-facing API being written in PHP.

In and of itself this is not an issue… except for the one thing I was trying to do.  One of the practices I’ve heard about Mongo is to get Mongo to do as much as it can, but not to worry too much about complicated joins and such as you would in SQL.  In other words, don’t shy away from bringing data into the application to do some processing.

That was the practice I followed, which worked fine up until my data size started to increase.  Then I ran into an issue where I was seeing 50% of my response time being eating up by BSONDocument and BSONArray unserialization calls.  This was due to a sub-document I had in the document that could actually be quite large.

“Hmm,” I thought to myself.  “I’m sure glad I didn’t see this a month from now.”  I did some research and waffled a little between using MapReduce or using the newish aggregation features.  I opted for the aggregation feature, which is so incredibly powerful.  I see myself misusing this quite often.

But after changing the code to make it work with aggregation I still had the problem of the unserialization.  The documents are returned as a whole.  In the core functionality you can exclude individual fields by doing something like this:

   { type: 'food', _id: 3 },
   { "classification.category": 0}

The second parameter (classification.category) tells Mongo to omit that field in the result set.  But I couldn’t find a way to mimic this behavior in the new library.  So I opened an issue on GitHub (when you run into a problem, contact the library maintainers or post on SO.  Don’t just leave it) asking how I might run this.

Jeremy Mikola responded with the solution.  There is a second option that you can put in that is documented, but I don’t think it is directly clear from the documentation exactly what it does.  Or, at least, the description isn’t very SEO friendly (Google-Based-Development FTW!).

How does that look?

Like this:

$find = [
    'customer_id' => $this->getId(),
    'invoked_test' => $testName
$options = [
   'sort' => ['created_at' => -1],
   'limit' => 10,
   'projection' => ['events' => 0]];

$currentResults = $tests->find($find, $options);

BOOM! 7.5 seconds off the response wall clock time.