incubator-flex-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Martin Heidegger ...@leichtgewicht.at>
Subject Re: Starting with the Whiteboard Code
Date Tue, 07 Feb 2012 05:44:24 GMT
On 07/02/2012 09:35, Michael A. Labriola wrote:
> Unfortunately, with a few exceptions, unit tests *cannot* be written 
> for the Flex framework. It isn't something that can be started.
Actually those "few exceptions" are quite many to me:
<https://svn.apache.org/repos/asf/incubator/flex/whiteboard/frameworks/projects/framework/src/mx/binding/>mx.binding.*
mx.utils.*
mx.collections.*
mx.events.*
mx.formatters.*
mx.geom.*
mx.graphics.*
mx.logging.*
mx.resources.*
mx.validators.*
mx.messaging.*
...

And yes: some of those classes do have "singletons" which means that the 
unit tests will be dirty a little. But never-the-less unit tests can be 
written for what looks like a quite big part of the project.
> Unit tests by definition involve the writing of a test for a single 
> object isolated from all other objects, not dependent upon global 
> state, that also means they can't be dependent upon things like the 
> frame rate and enter frame events. Looking at something like 
> UIComponent, it references singletons and static classes (global 
> state). It is coupled tightly with dozens of other objects. It relies 
> upon the LayoutManager, which relies upon the frames, to function.
Any system has at some point a static value. Java has it 
Thread.currentThread(), PHP has global constants, etc. If we could pull 
it of to create a unit test that encapsulates a component.

Take this part of the framework:
mx_internal static function get 
embeddedFontRegistry():IEmbeddedFontRegistry {
     if (!_embeddedFontRegistry && !noEmbeddedFonts) {
        try {
            _embeddedFontRegistry = IEmbeddedFontRegistry( 
Singleton.getInstance("mx.core::IEmbeddedFontRegistry"));
        } catch (e:Error) {
            noEmbeddedFonts = true;
        }
    }
    return _embeddedFontRegistry;
}

If we were to create a unit test environment that compiles against a 
UIComponent with a different set of code like:
mx_internal static function get 
embeddedFontRegistry():IEmbeddedFontRegistry {
    throw new RequiresFontRegistryError();
}
then if some part of the UIComponent that is being tested that relies on 
the font-registry would notify the test unit framework: "hey this 
component needs to be tested with a font registry". The unit-test writer 
now needs to Create two different subsets of his unit test: One in case 
the font-registry is given and one in case it isn't. Once he 
distinguished both tests the unit test framework has to run in both 
environments:

mx_internal static function get 
embeddedFontRegistry():IEmbeddedFontRegistry {
    return _embeddedFontRegistry||=new TestFontRegistry;
}
and
mx_internal static function get 
embeddedFontRegistry():IEmbeddedFontRegistry {
    return null;
}

A definition could look like this:
class UIComponentTest implements IStateTestSuite {
    public function get stateTests(): StateTestMap {
       var map: StateTestMap = new StateTestMap();
       map.set(ClassicTestContext, [UIComponentClassicTest]); // Classic 
test for things without static references (don't need to be tested 
within a context)
       map.set(FontTestContext, [UIComponentFontRegistryEnabledTest, 
UIComponentFontRegistryNullTest]); // FontTestContext will take two 
tests and run them in a endabled and disabled state.
       return map;
    }
}

I know it sounds like a horrible lot to write and test, but lets face 
it: It will not be simple to test code that relies on 14000 lines of a 
monolith that spreads its wings. I think with a little imagination, lots 
of willpower and a huge amount of coffee it might actually be testable.

yours
Martin.







Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message