Resource icon

Unit testing XenForo addons - tutorial

Sim

Well-known member
Sim submitted a new resource:

Unit testing XenForo addons - tutorial - Learn how to unit test your XenForo addons to make them more robust and error-free

1. Introduction

Unit testing is a process by which individual components (units) of your software are tested. The objective is to isolate a section of code and validate its correctness - ensure that it behaves as expected for the given inputs.

There are multiple levels of testing typically used in software development, including Unit testing, Integration testing, System testing, Acceptance testing and so on. Unit testing is generally the lowest level of testing...
Read more about this resource...
 

Sim

Well-known member
I have been using this package quite a bit to unit test my own addons - but at the moment they are all in private git repositories, so I can't share them for examples.

I will try and put together some examples over the next few days to show some real unit testing scenarios.
 

Jeremy P

Well-known member
This is really awesome. I've always felt that lack of decent test support was one of the larger remaining voids in the XF development space.
 
  • Like
Reactions: Sim

Sim

Well-known member
I must say that I continue to be deeply impressed with the architecture of XenForo v2 - just about everything I've tried to do has had an elegant solution thanks to the thoughtful approach @Kier @Mike and @Chris D have taken in getting the underlying structure right.

About the only thing still causing me grief is the Database layer - if we could just swap that out for SQLite running an in-memory database, we could do so much more from a testing perspective (build and then discard the database for every test!!)

I haven't yet looked to see how much MySQL-specific code there is which might stop us implementing a SQLite adapter for testing purposes.

Then I have to solve the issue of how to instantiate a fully functional XenForo application in the database quickly and efficiently so it can be done (and again, discarded) for every test - I have a few ideas about how we might do that, but haven't actually tried it yet.

Then there will be the task of creating factories to generate content - if we need a bunch of threads and posts created, we need to be able to do that programmatically in our tests. Laravel uses the Faker library with its factories that generate dummy content for testing - I'm hoping we can extend that same library to work with our entities for use with XenForo.

Lots of work still to do here!
 

Sim

Well-known member
I've pushed some test code to BitBucket which shows the assertBbCode function in action: https://bitbucket.org/hampel/content-bbcode-xenforo/src/develop/tests/Feature/PostBbCodeTest.php

PHP:
<?php namespace Tests\Feature;

use Tests\TestCase;

class PostBbCodeTest extends TestCase
{
    protected $boardUrl;

    protected function setUp() : void
    {
        parent::setUp();

        $options = $this->app()->options();

        $this->boardUrl = $options['boardUrl'];
    }

    // ------------------------------------------------

    public function test_bbcode_post_bad_id()
    {
        $bbCode = '[post=foo]view this post[/post]';

        $expectedHtml = '<div class="bbWrapper">[post=foo]view this post[/post]</div>';
        $this->assertBbCode($expectedHtml, $bbCode, 'html');

        $expectedHtml = '[post=foo]view this post[/post]';
        $this->assertBbCode($expectedHtml, $bbCode, 'simpleHtml');

        $expectedHtml = '<div class="bbWrapper">[post=foo]view this post[/post]</div>';
        $this->assertBbCode($expectedHtml, $bbCode, 'emailHtml');
    }

    public function test_bbcode_post_id_in_tag()
    {
        $bbCode = '[post=2]view this post[/post]';

        $expectedHtml = '<div class="bbWrapper"><a href="' . $this->boardUrl . '/posts/2/" target="_blank" class="link link--external">view this post</a></div>';
        $this->assertBbCode($expectedHtml, $bbCode, 'html');

        $expectedHtml = '<a href="' . $this->boardUrl . '/posts/2/">view this post</a>';
        $this->assertBbCode($expectedHtml, $bbCode, 'simpleHtml');

        $expectedHtml = '<div class="bbWrapper"><a href="' . $this->boardUrl . '/posts/2/">view this post</a></div>';
        $this->assertBbCode($expectedHtml, $bbCode, 'emailHtml');
    }

    public function test_bbcode_post_id_in_body()
    {
        $bbCode = '[post]2[/post]';

        $expectedHtml = '<div class="bbWrapper"><a href="' . $this->boardUrl . '/posts/2/" target="_blank" class="link link--external">' . $this->boardUrl . '/posts/2/</a></div>';
        $this->assertBbCode($expectedHtml, $bbCode, 'html');

        $expectedHtml = '<a href="' . $this->boardUrl . '/posts/2/">' . $this->boardUrl . '/posts/2/</a>';
        $this->assertBbCode($expectedHtml, $bbCode, 'simpleHtml');

        $expectedHtml = '<div class="bbWrapper"><a href="' . $this->boardUrl . '/posts/2/">' . $this->boardUrl . '/posts/2/</a></div>';
        $this->assertBbCode($expectedHtml, $bbCode, 'emailHtml');
    }
}
 

Banxix

Well-known member
I'm also struggling to make proper and thoroughful tests for XF. To think that we need to build a large system without tests is a nightmare.
 

Sim

Well-known member
I'm working on releasing a couple of updated addons which will include extensive unit tests - hopefully they will be useful as examples of the types of things you can do.
 

Banxix

Well-known member
I'm working on releasing a couple of updated addons which will include extensive unit tests - hopefully they will be useful as examples of the types of things you can do.
That would be great.

As of right now, to write tests for XF, one need to read whole (or part) of XF code base thoroughly. For example, cache system of entity will make two entity objects being equal in some circumstances (heard from DBTech). Sometime, it is not a viable solution to read and understand core methods in a short time, if you're not familiar enough.
 

Sim

Well-known member
Sim updated Unit testing XenForo addons - tutorial with a new update entry:

v1.1.0 update

  • Feature: added new functionality to Interacts with Extension
    • isolateAddon
  • Feature: Interacts with Registry - adds:
    • fakesRegistry
  • Feature: Interacts with Filesystem - adds:
    • swapFs
    • mockFs
  • bugfix: after mocking the database, set up the entity manager again, so we get the mocked database
  • bugfix: should pass options array through to parent
  • bugfix: cleaned up function visibility for consistency
  • bugfix: override...
Read the rest of this update entry...
 

Sim

Well-known member
I have recently released a new addon - Geoblock Registration, for which I have written unit tests which are available for viewing in the source code on Bitbucket (the unit tests are not included in the addon release files) - https://bitbucket.org/hampel/geoblock-xenforo/src/master/tests/Unit/

Hopefully this will give people some ideas about how you might go about writing unit tests for your own addons using this testing framework.

Each test file concentrates on a single class and each method tests a specific code path through one of the public methods.

I have another new addon which I will be releasing in the next week or two which will also have extensive unit testing available - I will post a link to the source code once that is available - it will utilise some other aspects of the framework not used by this addon.
 
Top