Showing posts with label Luis Majano. Show all posts
Showing posts with label Luis Majano. Show all posts

Thursday, 16 July 2015

CFML: ColdFusion does some dodgy exception "handling"

This was a curly one. I've been doing some testing recently, so I've been giving TestBox a bit of a thrashing. Yesterday I was a bit bemused that some of my tests were failing (that's not actually any sort of surprise given what I'm testing. Ahem), but other tests were erroring. yet they were testing much the same thing, and the condition causing the failure was the same for both the failing and erroring tests. I thought there was something weird afoot with TestBox, so I hit-up Luis about it.

I boiled the repro down to this:

// ErrorInsteadOfFail.cfc

component extends=testbox.system.basespec {

    function run(){
        describe("Replicating issue", function(){

            it("demonstrates a baseline", function(){

            it("demonstrates the error", function(){
                var results = [1,2,3];



This is really contrived, so don't pay too much attention to the code. Just focus on these two bits:

  • calling expect() directly in my test;
  • calling expect() within an iteration function, within an inline function expression.

The expectation on each is the same: that false is true. Which it isn't (I'm not going too fast, right? ;-), so the test should fail.

However I get this:

Notice how the second test isn't failing, it's actually erroring.

I raised a ticket for this: TESTBOX-127.

Luis came back to me a coupla hours later with the interesting observation that it seems when an exception is thrown within a closure, then ColdFusion doesn't just let it error, it wraps it up in a different exception, and throws that.

That's a bullshit thing for ColdFusion to be doing. Lucee, btw, does not do this: it behaves properly.

I expanded my tests out to cover a couple more things:

Saturday, 18 October 2014

PHP: getting AspectMock to work

First things first: Luis, Brad, everyone at Ortus Solutions: I bloody love you guys. Working with TestBox and MockBox is an absolute pleasure compared to getting their PHP equivalents installed and working properly.

Over the last coupla weeks, meself and Duncan have been investigating unit testing on PHP, and specifically how to mock dependencies. On our old CFML code base, we have 1000s of test, and we use MockBox heavily, as we have rather a lot of dependencies which interfere with testing if they're not mocked. We only ever really moved to TestBox as a proof-of-concept before our CFML codebase was put into maintenance mode, and we shifted to PHP. Prior to that we had been using MXUnit for a number of years.

PHPUnit is a bit rough-and-ready in comparison to TestBox, but it's solid and will do the trick. However we both had an arsehole of a time getting AspectMock to work. And we both failed and moved on to other things. Earlier I'd looked at Mockery as a solution for mocking - its docs are better than AspectMock's (both a recommendation for Mockery, and an indictment of AspectMock), but it did not do something things we expect to need to be doing, whereas AspectMock claims it can (mocking static methods).

Anyway, this afternoon I found myself furrowing my brow and thought "I'm going to get that bloody thing to work... or else". Fortunately after a lot of swearing and wondering if I can hunt down and punish AspectMock's author... I finally noticed what I had been doing wrong. I presume Duncan was doing the same thing wrong, but don't know. Anyway, I got it working.

So here's my AspectMock mission from this afternoon.

Monday, 9 June 2014

Ortus does what Adobe / Railo ought to have done...

Luis & Brad (and Alex from Pixl8) have been offering teasers for CommandBox for a while now: Luis first showed me at CF.Objective(), and had been talking about it before then. Today they released a "trailer" for it: "Teaser Video for CommandBox". Go watch it.

Thursday, 22 May 2014

London Railo Group: but wait... there's MoreBox

Blimey... not one but two London Railo Group meetings next week. On Friday Pixl8 are hosting Luis, who's gonna be showing off CommandBox, which is a CLI for CFML. As well as that Alex (and/or Dom?) are going to be demoing the revitalised PresideCMS. Details here: "Luis Majano (New Coldbox and CommandBox) , Pixl8 PresideCMS Sneak Peak".

I have to concede I don't have content to manage, so CMSes aren't something that're on my radar, but Alex has shown me bits 'n' pieces of PresideCMS, and I am really really impressed with what he and Dom have done with it. It's a cliche, but it really seems like they've taken CMSes to the next level.

Luis showed me a bit of CommandBox at CF.Objective(), and it looks really bloody excellent. Definitely covering territory that the CFML platforms themselves should already be covering as far as package management and CLI goes.

I really wish I could be at this presentation too, but I'll be over in Ireland seeing my boy, and that's a lot more fun than CFML stuff. Sorry guys ;-)

But I urge you to sign up for this meeting as well (as the Railo one on Tues: "London Railo Group: Gert's over").



Monday, 23 December 2013

Being loosely typed is often a good thing but...

Here's the upshoot from something that bubbled up on Twitter. I'll spare you the replicated timeline this time, and just cut to the chase...

Saturday, 21 December 2013

CFML: Follow-up to last night's article about a TestBox "bug". PEBCAK strikes again!

Time for me to fall on my sword.

Yesterday I started looking at TestBox ("Unit Testing / TDD - switching off MXUnit, switching on TestBox"), and whilst messing around, I came across a coupla bugs (some legit, I hasten to add), one of which Luis asked me to clarify on the ColdBox mailing list. Which I did: "[Testbox v1.0.0] "Variable ISEXPECTEDEXCEPTION is undefined" on erroring test".

The gist of this is as follows:

// Tests.cfc
component {

    public void function beforeTests(){
        variables.beforeTestsRun = true;

    public void function setup(){
        variables.setupRun = true;

    public void function testInitFunctions(){
        assert(structKeyExists(variables, "beforeTestsRun"));
        assert(structKeyExists(variables, "setupRun"));

    public void function testThatErrors(){
        throw(type="TestException", message="This is a test exception", detail="Note that it is NOT being caught / tested for. This is by design");

    public void function testThatFails(){
        fail("This test should fail");


This is a distillation of my situation, not actual code. I am testing TestBox's MXUnit compatibility "mode", so here's a test that checks that beforeTests() and setup() run, plus how it deals with an erroring test, and a failing test.

When I was running this on ColdFusion, I got this output:

TestBox v1.0.0.00062

Global Stats (86 ms)

[ Bundles/Suites/Specs: 1/1/3 ] [ Pass: 1 ] [ Failures: 0 ] [ Errors: 2 ] [ Skipped: 0 ] [ Reset ] 

shared.git.blogExamples.unittests.testbox.Tests (18 ms)

[ Suites/Specs: 1/3 ] [ Pass: 1 ] [ Failures: 0 ] [ Errors: 2 ] [ Skipped: 0 ] [ Reset ]
Note how the erroring and failing tests were reporting as erroring, but with an error internal to TestBox, not with the expected output MXUnit would give. So basically when a test failed or errored, TestBox itself was failing.

At this point... can you see what I've done wrong here?

Here's the thing. For TestBox test CFCs, there is no need to extend anything. I guess TestBox just uses mix-ins to insert all its bits and pieces. So my CFC doesn't extend anything.

However with MXUnit, one does need to extend mxunit.framework.TestCase.

Obviously on all my "normal" MXUnit test CFCs I do have the correct inheritance in place. But this particular test CFC started out with me testing TestBox tests, not MXUnit tests, so I neglected to put the inheritance in when I switched over to running it with MXUnit compatibility "mode". My bad.

Once I sorted that out, my tests run fine:

TestBox v1.0.0.00062

Global Stats (82 ms)

[ Bundles/Suites/Specs: 1/1/3 ] [ Pass: 1 ] [ Failures: 1 ] [ Errors: 1 ] [ Skipped: 0 ] [ Reset ] 

shared.git.blogExamples.unittests.testbox.Tests (15 ms)

[ Suites/Specs: 1/3 ] [ Pass: 1 ] [ Failures: 1 ] [ Errors: 1 ] [ Skipped: 0 ] [ Reset ]

I fed this back to Luis, so that's case closed on that one. I also editorialised a bit, saying this:

It's a pity your test case CFCs don't need to be of a certain type, as that would have clarified that error from the outset. It would also help mitigate a failing MXUnit always had in my opinion: that it determines whether a CFC is a test CFC by its NAME rather than its TYPE (eg: it's a subclass of TestCase). This name-based approach isn't great OO, especially if the capability to do it "properly" is right there.

This has always annoyed me about MXUnit. And it'll annoy me about TestBox. It doesn't annoy me much, but that MXUnit always relied on a file-naming scheme to identify test CFCs always seemed a bit amateurish to me. [gallic shrug]... this is a very minor gripe, and I do not forget that MXUnit has still been one of the most useful CFML tools out there, and TestBox is almost certainly gonna be an appropriate successor.

And Luis... very awesome you followed up my mailing list question so promptly. Much appreciated. I need to venture out into an uncharacteristically windy London for coffee and food, but I shall be writing more tests today. Let's see how it goes...


Sunday, 20 October 2013

CFML: Threads, callbacks, closure and a pub

I'm over in Ireland this weekend, and am doing my normal Sunday afternoon activity of sitting at Shannon Airport drinking Guinness, having finished my business early, so have a 4h wait in departures before my flight even considers boarding. Today's excitement here was the 500-odd US Army squaddies in transit to or from what I presume was Afghanistan. It makes a change from being the only person in the place, which was the case two weeks ago (other than shop staff, that is). Last night I killed some time in the pub too, during which I knocked out some quick code, to solve a problem I invented for myself to kill time. Here's the result.

A week or so ago Luis started an interesting thread on the Railo Google Group: "Add closure support to blocking operations to allow them to be non-blocking operations.". The summary of which is:

[...]I propose adding closure callback support to the following functions/operations so they can be processed natively in the background (non-blocking) and then call back when done.


Basically any operation that can block a network or local resource.  Imagine doing this:

fileRead( file, function(contents){
  process file here in the background once it is read.
The bits I omitted ([...]) are simply for abbreviation, and preserve the gist of his suggestion. This is a reasonable idea in general, but - as I go on to say in the thread - I don't think the suggested approach is very good for a coupla reasons. It's not bad, but it just seems a bit "embryonic" to me. But this is fine, this is what discussion forums are for.

My suggested approach would be more all-encompassing. Why limit this functionality to a subset of predetermined built-in functions? What about other built-in operations that might be slow, but otherwise doesn't need to interact with the rest of the code subsequent to it in the request? What about custom code that is similar? It makes little sense to me to "hard-code" this sort of behaviour to specific operations, to me.

A better solution would be to provide a general mechanism that can be used by any code to background-thread its execution, and fire callbacks on completion, failure etc, so as to kick off the next process, or flag-up that the process has completed.

Then it occurred to me that I thought I could knock a solution out to this using a single function. Not a very complete solution, but a solution nevertheless.

So sitting at the bar last night, over the course of four Guinnesseses, I came up with this lot:

Friday, 11 October 2013

CFML: A possible variation on the thread idea...

I can't take sole credit for this idea, because when reading something Luis said today on the Railo Google Group, I had an epiphany. Let's have a look at <cfthread> (or, indeed, just thread) again...