I am working on a regression testing framework which might be useful for fully automated testing of all frontend components. "Automated" in terms of not having to write any specific test.

It's called "SiteEffect" (http://siteeffect.io) and I gave a session about it at the Dev Days in Szeged. I uploaded the slides, but I'm not sure how useful they are. I'll most likely (if accepted) give the session again at drupal camp main in frankfurt.

I have started to make it work with Drupal 8 and will post any updates and more details here soon. I discussed the basic idea with a lot of the DDD attendees, including tstoeckler, da_wehner, dasjo, rteijeiro, pixelmord, schnitzel, nod, yesct, ....

The whole issue is related to #237566: Automated JavaScript unit testing framework, but not that same as it doesn't do any functional testing.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

LewisNyman’s picture

Ah I've had an issue open for visual regression testing for ages. I would really like something like this. #2099579: Discuss automated visual regression testing

YesCT’s picture

Issue summary: View changes

I saw a demo in the sprint room at Szeged. It was very impressive.

We talked about sometime in the future about the possibility of marking the "regressions" as features (stuff wanted to change), export of information in a file. Then the next version of a patch, could use that file, and know which regressions were desired (if they were marked so earlier).

ti2m’s picture

SiteEffect has a build in crawler, but adding relevant D8 urls manually is tedious. On the other hand adding all urls automatically would lead to an explosion of urls, e.g. with all watchdog messages. The idea was to get the router item behind every url and only add one url per router item. I got the basics to work at the dev days after talking to dasjo and klausi. I now finished the integration into siteffect. Without any other then the default core modules enabled I'm now capturing 223 urls.

I have tested the patch to remove the misc icons (#1356602-19: [META] Clean up icons in misc) which got reverted because it removed the 'configure-dark.png' which was still used on the "Manage Display" page. SiteEffect detects the missing icon as well, but of course fully automated.

Tables as you can tell are not being handled correctly by siteeffect right now as I didn't look into it yet. Most important thing is though that changes are being detected and you can easily check through the SiteEffect UI that images are missing. The siteeffect url overview below shows the three failed urls, which are all missing the icon. Note that only 'article' is being checked as all 'page' urls go back to a menu router item that is covered through 'article'.

This is not ready at all to run fully automated on a remote server somewhere, but this will be my main focus in the near future. Up until then I can always run tests locally if anyone is interested. It would be good to test other patches, especially those changing the themes or frontend.

tstoeckler’s picture

Awesomesauce^1000 !!! :-)

I really love the work you've put into this. The fact that you caught that icon regression with SiteEffect is pretty impressive.

The approach of not managing URLs but routes makes a lot of sense, IMHO. You've already hit a pretty big limitation of that, though: We would ideally want some sort of per-route variants. I.e. all node pages (i.e. /node/%) are handled by a single route yet they can contain completely different markup based on node type. I.e. in a perfect world we would probably capture an 'article' page *and* a 'page' page. With panels in the mix (which is exactly the meaning of 'variant' that I borrowed here) this becomes even more important. Not sure how to do that, though.

AFAIK admin_menu in D7 has some code to do this, i.e. you can drill down into the list of content types or views within the admin menu, even though those are handled by a single route. It's sort of a different use-case but it feels related. Maybe we need something like that in core. Would be pretty cool to have that feature for the new navbar, as well. Not sure, though...

ti2m’s picture

Thanks for the feedback. I'll take a look at admin_menu, I assumed they do some hard coding to e.g. show all urls for the content type route, will see. Right now I'm handing all new urls from SiteEffect to a tiny custom D8 service, which then resolves the url to the route and sents it back. SiteEffect checks if the route isn't yet present within the urls and then adds it. BUT SiteEffect doesn't care about the route itself, it just sees it as a unique url identifier, therefore on the D8 site we can just append e.g. the nid to the route string. This would actually be quiet nice as you can then decide per site which urls you want to track. That would be the SiteEffect contrib module then.

Another problem I see is dummy content / config though. Testing everything without nodes, views, languages, placed blocks etc. probably doesn't make too much sense. Do we have some installation profile for that? Do we need to come up with one? In that case it would be good to come up with a list of needed dummy content and data.

YesCT’s picture

1. re content in core: https://groups.drupal.org/snowman is about having content in core (maybe ... not so sure now).

2. Question: How does it know how to configure the site so that all the routes are testable.
For example, language, content translation need to be installed, and set up to be able to test translation related pages.

catch’s picture

#913086: Allow modules to provide default configuration for running tests and #1551600: DBehave! are both relevant, and probably more to here than Behat.

YesCT’s picture

Issue tags: +frontend, +Testing system
dawehner’s picture

Posting a link to test (this is mostly frontend and or admin menus)

TechNikh’s picture

I have added Automated frontend testing feature to Drulenium (Drupal + Selenium) module (https://drupal.org/project/drulenium)
Comparing drupal 8.0-alpha11 with drupal 8.0-alpha9 identified some potential issues in Drupal8 code, as mentioned here http://nikhil.dubbaka.com/blogs/drulenium/automated-frontend-testing-dru...
alpha11 Issues:

  1. Responsive table missing "Show all columns" option.
  2. Textarea height is more than required
  3. More white space than required
  4. Development Configuration moved from second column to first.

@ti2m Like to talk to you more on this.

ti2m’s picture

Wim just send me a link http://www.phpied.com/css-diff/ which creates gifs based on phantomjs and imagemagick. @TechNikh gifs are also the main output of your solution, right?

The problem that I'm having with gifs are kind of the same that I'm having with pixel diffs. I still can't really tell where the src of the change is, e.g. can anyone tell me what happened here: http://www.phpied.com/files/diffcss/tmp/dif.gif
Did the width change, margin, padding? On which element... and it get's a lot worse when you have more then one change on the page.The other problem I see with gifs is that you have to check all pages manually if they throw any error at all.

TechNikh’s picture

FileSize
270.81 KB

@ti2m Good point. Definitely GIFs don't show what changed in source code but show the change and where it happened as seen by a user.
Not sure how much we can rely on automatic suggestions of changed DOM elements(width, margin, padding... definitely helpful to have) but I think the user can pretty much debug by inspecting element once he knows where the bug is. Since the developer knows what changes are made with version control it shouldn't be that pain to identify the bug in code. Better results with testing often and shorter iterations.

for example:

Drulenium(https://drupal.org/project/drulenium) shows how much percentage of pixels are different and shows the GIF link only when the "before snapshot" is different from "after snapshot". So no need to check all GIFs manually for error. If there is a GIF, there is a wanted/unwanted change.

I think gifs work great in most of the use cases like

  1. Performance optimizing the site with caching as shown at http://nikhil.dubbaka.com/blogs/acquia/automated-visual-testing-zero-coding-will-save-you-thousands-dollars
  2. Site upgrades(Core, contributed modules, themes...)
  3. Site Migration from one hosting server to another
znerol’s picture

ImageMagick also has a compare-command capable of creating "image diffs". Over at Piwik they use that together with PhantomJS for UI regression tests.

TechNikh’s picture

@znerol In the backend, https://drupal.org/project/drulenium uses ImageMagick to create GIF and Resemble.js (https://github.com/Huddle/Resemble.js) to produce output like Image diff by Resemble.js

https://github.com/Huddle/PhantomCSS uses PhantomJS and Resemble.js for UI regression tests.

ti2m’s picture

Title: Automated frontend regression testing » SiteEffect: Automated frontend regression testing

@znerol @TechNikh Maybe you can open separate issue for your tools and link them to the overall issue #2099579: Discuss automated visual regression testing as I open this issue here in particular to post updates on SiteEffect and this is already starting to get out of hand. I therefore changed the title of the issue.

I'll have the next two weeks to just work on siteeffect, so there will hopefully some major progress.

TechNikh’s picture

@ti2m
I want to make https://drupal.org/project/drulenium able to support different Testing techniques to allow the user to pick which service He/She wants to test with.
If SiteEffect has an api, the user can register on SiteEffect, put the api code in Drulenium module and the module can send that information to SiteEffect to start testing.
This way the user need not enter the page paths he want to test in SiteEffect or SiteEffect need not crawl the website to get the pages.
Since the drulenium module is installed in a Drupal website the module knows about the pages of the site.

If the user is tech savvy, they can also have the option to install selenium server and ImageMagick locally and use that instead of remote services.

Any thoughts on this?

Fabianx’s picture

@ti2m

I like the work going in here. I still think it would be good (like the drulenium author) to be able to feed siteeffect.io with pairs of:

{ variant: 'e.g. drupal8-alpha1', url: '/node/1/delete/confirm', hash: 'hash-of-meta-data', metaData: { method: 'post|get', data:{post_data_here} } , source: 'html source'}

where:

- variant is the site version to be tested
- url is the URL / route that is tested
- hash is an additional modifier to the url / route that can represent variants
- metaData: is additional metadata useful to find what triggered the problem, e.g. POST data, etc. for a route: content type
- source: the retrieved HTML source

The idea being that we can turn our D8 test suite into a provider of amazing amount of data that siteEffect could process and analyze then.

Is something like this possible? To feed data from an external system into SiteEffect.io?

I can probably simply enough provide you with all the data represented above, but analyzing it is the hard part and that seems something you have solved already.

Thanks,

Fabian

Fabianx’s picture

FileSize
16.49 KB

Soo,

I have a working patch now that visits and records the output of all URLs in the Drupal system using the test suite.

How can we combine that with SiteEffect.io?

See attached patch:

Where there is the file_put_contents() one would need to call SiteEffect.io to create a snapshot of the saved URL as e.g. a file might only be available during the test run after a specific POST. Or just have SiteEffect.io visit the saved URL, which works great with e.g. webpagetest.org.

I tried regular diffs and time() and REQUEST_TIME have been the biggest culprits in how things are different, the attached patch has the hacked time handling disabled (as I still had test failures with it).

How did you handle dates and other elements that naturally change from page to page visit in SiteEffect.io? Just very curious.

Anyway, I don't get further with the diff approach atm, so I am relying on SiteEffect to parse useful data out of the huge amount of URL data I can produce now.

I hope this is useful in a way.

ti2m’s picture

Sorry, for the late response, I wanted to try a couple of things but didn't get to it yet. There will be an API for siteeffect at some point, but this will take some time. Besides that, siteeffect records so called "snapshots" which consist of A) a full sized screenshot and B) a DOM like representation of the page with key values. This means that simply handing siteeffect a screenshot will not be sufficient as siteeffect does a lot more then "just" compare images. What siteeffect therefore needs to work properly are callable urls.

@fabianx I didn't quiet get the data format / the meaning of the data in comment #17. SE uses webdrivers to collect all the data, in particular I'm using the "nodejs wd" module. But if I get it right then your patch makes it possible to save e.g. a node deletion confirm page to a static html file??? If that file contains the rendered html with the original script and css file references then it would be really easy for me to process these. I just need to open the files through the webdriver and can record all the data I need. If that really worked then we could make major progress here!!!

Handling content changes like the timestamps you mentioned is one of SE main focus areas. SE creates the following view

You can then mark/flag these changes (layout, text, pixel) and SE will then ignore these changes in future testrun. This is possible because SE doesn't just work on images, but on mapped elements. Right now you can only define ignored elements through CSS selectors globally, so not per test, but this will change soon. I'm also working on automatic generation of the shortest unique CSS selectors for elements, then you can just flag elements through the UI. Need a day or two to get this fully working, as mentioned, siteeffect is still under heavy development. The real potential though lays in detecting where changes are actually coming from. As another example one of the screenshots from the twig testruns:

SE gets that the search field, forms block etc. shifted down because of the changed heading and therefore doesn't mark it as a change / error. This isn't really necessary for core development as hard regression testing might suffice, but it will be really useful for real projects.

But back to topic. Would you be able to sent me some of the dumped test data? I could try to get your patch up and running, but it will - as always - take me couple of hours, time I just don't have right now. This way I could easily test if this could work in general.

Fabianx’s picture

>But if I get it right then your patch makes it possible to save e.g. a node deletion confirm page to a static html file???

That is correct and that bit passes tests even:

https://www.drupal.org/node/2280195#comment-8894029

I today build my own testbot on AWS, so it won't take ages to complete generating the data. I will let it run overnight and hopefully tomorrow have a full set of files for you to process.

> If that file contains the rendered html with the original script and css file references then it would be really easy for me to process these. I just need to open the files
> through the webdriver and can record all the data I need. If that really worked then we could make major progress here!!!

Finally someone that is as excited as me about this :-D. It might be that some data would not be available due to a file e.g. being only available at a certain state during the test run. That is why I thought to callback to your webdriver and interrupt the testing.

But yes, lets give the static files a try. I used webpagetest.org and it for most tests could correctly generate HAR data (well for those I tested), which is nice as this means this can in parts also be used for front-end performance testing.

One thing I could not find out was how to get from an URL to a route as I would have preferred to save it to routes, but for now URLs it is ...

I'll send you a mail via contact form once I have data and test run completed.

Fabianx’s picture

@ti2m:

I have send all dump'ed test data over to your email. Let me know what you need more and when I can create more data! Enjoy!

Fabianx’s picture

Btw. latest patch to just dump the data and not care about the time:

http://cgit.drupalcode.org/sandbox-Fabianx-1819382/diff/?h=8.x--vtd--sim...

ti2m’s picture

Wow, this is fantastic and closes the gap I had no clue how to deal with. Looks like I'm talking to the right person here :)

The amount of urls is huge, at the moment siteeffect won't be able to handle 7000+ urls and it will take foreever to run all tests for the urls. Something like this isn't really the scenario I have been planning on to deal with. I would need to implement a simple routine to check if anything even changed at all, something like checksums on the PNGs and DOM files, that way I could save a lot of computations. This would be basically a preprocessing step. Besides that I need to reuse the webdriver session as right now for every tests the browser will be killed, caches cleared, etc. If I reuse a browser session it should speed up things a lot. It's all in the siteeffect backlog, but there are other more critical issues I have to work on before that.
We could look into more basic pixel-diff approaches, but these will also take quiet some time to run as they need to load the pages, save the screenshot and do a full pixel diff.

I have tested the first 100 urls and it all works, which is really great news. I "just" need to scale it. So this might take some time, sorry! If only I had more time... the usual. I'll think about how we could make some more progress here quickly. Maybe you can set up wraith (phantom + imagemagick) and filter the urls which are 100% identically and siteeffect then handles the rest of the urls which differ for whatever reason. Thoughts?

Maybe you could spin up a second instance with the twig patch, I can give siteeffect two different urls for master/dev version of a page. We could then test if this works with a couple of the know failing urls. Just to make sure it all works in general. Just an idea.

I will sent you the code for getting the route of a url, maybe you can make use of it.

Fabianx’s picture

Thanks for the route code, I will see if I can get it to work with that.

Yeah, definitely want to do some pre-filtering on that.

I hoped SiteEffect would be able to blacklist always changing things automatically, but I can see the resource problem :).

I'll do some test runs today evening to compare 8.x and 8.x--autoescape2.

I\ll probably normalize the URL structure but not the hostname and just have vtd--8.x/, vtd--autoescape2/ directories with the recorded results, then just give those out that are way different.

Thanks again!

ti2m’s picture

I implemented a PNG CRC checksum and session reuse in a nightly session, so we could give it another try. The urls seem to have changed tough, am just getting an access denied.

Fabianx’s picture

The URLs are back. Sorry for the trouble. I had renamed the directory, but forgot to update URL.txt. Should have time later today to continue work on that.

ti2m’s picture

Thanks! The session and checksum improvements seem to do the trick. I captured 1000 urls in under 30min with two processes running in a VM. Roughly the same for the diff phase. As this is kind of an extreme scenario I think it is quiet ok, a decent server will be able to do much more then that. My UI will burn though if I put 7000+ urls in their though, but I could try to do it batch wise for now. What would be super useful would be another directory with the output of the patched test runs. Then I can compare them directly and switch forth and back as need. Not sure when I would have time to look into it though, maybe next week at some point.

YesCT’s picture

Can we see what the results would have looked like for #2349829: #2293589 breaks table row buttons ?

Fabianx’s picture

We are still working on it, FWIW.

The next step is to get the Deterministic Random Number Generator in place I think.

ti2m’s picture

I'm pretty sure SiteEffect (or any other visual regression test) would have caught this. I spend quiet some time to make all the dates deterministic, some tests now still fail for whatever reason, but it looks like 98% of the tests are fine with the hack. It's a really evil hack, as I even need to replace the usage of native PHP Datetime(). This will never go into core, so we need to solve the problem of how a reroll of the patch can somehow be automated. Right now I'm using PHPStrom to refactor and replace function calls with my own testing mockup functions.
With Fabianx's approach of writing all test pages to files I now get more then 11.000 urls. I need to take a day and put it all together, working with the testbot is always time consuming. But I'm convinced that this will work! If I got this working I will test the issue mentioned in the comment above and the initial issue of twig autoescape and post the results.

YesCT’s picture

This is great news.

Also, #1842140: Remove title and wrapper div from item-list.html.twig is interested in the results it has.

ti2m’s picture

@YesCT thanks for linking the issue. I think I need to switch strategies, getting the testbot output to work will take way more time then expected. I tried to reroll the working patch from 2 weeks ago against head and I got tones of merge conflicts. I have now tried to replace function strings through regex and sed, but the outcome seems to differ from my patch. Besides that there are still issues with UUIDs not being deterministic between runs. Lot more work is needed here.

Therefore I think in the meantime I'll go back to the approach of testing all kinds of urls of a fresh installation with all modules enabled. That already worked at some point, I only need to see how I can automate the whole process, but that shouldn't be to difficult on AWS or digital ocean.

YesCT’s picture

Yeah, getting something running that we can use would be great, and then we can improve on it.

YesCT’s picture

ti2m’s picture

platform.sh seems to be a good option to easily spin up new installations with specific patches. I'll have some time tomorrow to take a closer look. Testing RTL shouldn't be a problem.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.