FlexUnit 4 for contributors
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

FlexUnit 4 for contributors

on

  • 1,895 views

Architecture overview of the FlexUnit 4 project

Architecture overview of the FlexUnit 4 project

Statistics

Views

Total Views
1,895
Views on SlideShare
1,869
Embed Views
26

Actions

Likes
3
Downloads
32
Comments
0

1 Embed 26

http://www.slideshare.net 26

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • test is to method as Strictly: one test per branch through code so an if statement will usually mean that you should have multiple tests per method
  • Test cases are normally contain more that one test
  • Usually test cases are associated with classes, and each tests in the class exercises a piece of functionality of the class
  • Test suites are usually associated with applications and normally contain multiple test cases for each of the classes used in the application.
  • Point out test is to method as -> many method tests per class test case is to class as -> many class tests per application test suite is to application -> possibly multiple test suite
  • This is a simplified view test runners not shown test cases in the same suite may be run by different runners.
  • Technically one could disallow the suite method, but this describes default behavior

FlexUnit 4 for contributors Presentation Transcript

  • 1. FlexUnit 4 for Contributors Michael Labriola Digital Primates twitter.com/mlabriola blogs.digitalprimates.net/codeSlinger/
  • 2. Who are you?
    • Michael Labriola
    • FlexUnit 4 Lead
    • Senior Consultant at Digital Primates
    • Flex Geek
    • Team Mentor
    • Fan of Working Code
  • 3. What is this session about?
    • FlexUnit 4 Architecture
    • This session is designed to give a crash course in the FlexUnit 4 architecture for those we hope will contribute to the project
  • 4. A few things to Note
    • FlexUnit 4 is an open-source project hosted by Adobe but driven by the community
    • FlexUnit 4 is named with the 4 suffix as it has approximate feature parity with JUnit 4. It can be used with any version of Flex
    • FlexUnit 4 can be compiled without Flex dependencies making it viable for AS only
    • projects as well
  • 5. Starts with a Test
    • [ Test]
    • public function testMe():void {
    • }
    Test
  • 6. FlexUnit 4 Test Case
    • package {
    • public class SomeTestCase {
    • [ Test]
    • public function testMe():void {
    • }
    • }
    • }
    Test Case Test
  • 7. FlexUnit 4 Test Case
    • package {
    • public class SomeTestCase {
    • [ Test]
    • public function testOne():void {
    • }
    • [ Test]
    • public function testTwo():void {
    • }
    • [ Test]
    • public function testThree():void {
    • }
    • }
    • }
    Test Case Test Test Test Test
  • 8. FlexUnit 4 Test Suite
    • package {
    • [ Suite]
    • [ RunWith("org.flexunit.runners.Suite")]
    • public class SomeTestSuite {
    • public var someTestCase:SomeTestCase;
    • }
    • }
    Test Suite Test Case Test Test Test Test
  • 9. FlexUnit 4 Test Suite
    • package {
    • [ Suite]
    • [ RunWith("org.flexunit.runners.Suite")]
    • public class SomeTestSuite {
    • public var someTestCase:SomeTestCase;
    • public var someTestCase2:SomeOtherTest2;
    • public var thirdTestCase:ThidTestsCase;
    • public var anotherSuite:AnotherTestSuite;
    • }
    • }
    Test Suite Test Case Test Test Test Test Test Case Test Test Test Test Test Case Test Test Test Test Test Suite Test Case Test Case
  • 10. Flex Unit 4 Core
    • core = new FlexUnitCore();
    • core.run( SomeTestSuite );
    FlexUnitCore Test Suite Test Case Test Test Test Test Test Case Test Test Test Test Test Case Test Test Test Test Test Suite Test Case Test Case
  • 11. Flex Unit 4 Core
    • The FlexUnit core is responsible for executing objects that implement an IRequest interface
    • You can pass it an IRequest directly or, if you pass it another type of class, it will attempt to create a Request on your behalf
  • 12. Flex Unit 4 Request
    • For right now, imagine a request as an object that wraps your tests when they are presented to the core
    • Requests can be filtered and sorted to control the subset and order of tests executed
    Request Runner:Suite Test Suite Test Case Test Test Test Test Test Case Test Test Test Test Test Case Test Test Test Test Test Suite Test Case Test Case
  • 13. Flex Unit 4 Core
    • When creating your own requests, you generally use the methods of the static Request class
    • Common methods include:
    • aClass()
    • classes()
    • runner()
    • method()
    • sortWith()
    • filterWith()
    • Request.method( TestAssert, "testAssertTrue” )
    • Request.classes( TestAssert, TestAsynchronous)
    • .filterWith( someDescription )
    • .sortWith( mySortFunction );
  • 14. Flex Unit 4 Core
    • If you pass FlexUnit 4’s core anything other than an IRequest, the core uses these methods to generate a Request object before processing continues
    • Ultimately, FlexUnit4 runs 1 and only 1 request per run. So, if you pass it multiple classes, etc. these are all wrapped in a single Request before execution begins
  • 15. Flex Unit 4 Request
    • The key property of the IRequest that the FlexUnit core needs is the IRunner.
    • IRunner is an interface implemented by any object capable of executing a specific type of test
    • For example, there is a runner that understands the work needed to execute a suite. A separate runner understands how to execute test cases and methods.
  • 16. Flex Unit 4 Request
    • To determine the correct IRunner for the request, the Request object kicks off a recursive process of introspecting each class
    • Identification Process
    • Introspect the class
    • Identify the runner for the class
    • Identify any children
    • Run this process on each child to identify their correct runner
    • Return the top level runner for the Request
  • 17. The Correct Runner
    • FlexUnit 4 determines the correct runner for each class using builders
    • Builders are objects responsible for building the correct runner for a class
    • We try multiple possible builders until a compatible one is identified
    • Default Possibilities
    • Ignored Builder
    • MetaData Builder
    • Suite Method Builder
    • Flex Unit 1 Builder
    • Fluint 1 Builder
    • FlexUnit 4 Builder
  • 18. Ignored Builder
    • Looks for the [Ignore] metadata on top of the class
    • If this metadata is found, it creates an instance of the IgnoredClassRunner, which simply knows how to report that this class has been ignored back to the core
  • 19. MetaData Builder
    • Looks for the [RunWith] metadata on top of the class (remember our suite example?)
    • If this metadata is found and the runner specified can be found, the builder checks that it implements the IRunner interface. If so, it creates an instance of the specified runner to run this class
    • This provides a huge hook for extensibility
  • 20. Suite Method Builder
    • Checks if the given class specifies its tests with a static suite() method
    • If this method is found, it creates an instance of the SuiteMethodBuilder which will later decipher the contained tests
  • 21. FlexUnit 1 Builder
    • Checks if the given class descends from flexunit.framework.TestCase in the FlexUnit .9 library
    • If this is a subclass of TestCase, it creates an instance of the FlexUnit1ClassRunner.
  • 22. Fluint 1 Builder
    • Checks if the given class descends from net.digitalprimates.fluint.tests.TestCase or net.digitalprimates.fluint.tests.TestSuite in the Fluint (presently 1.2) library
    • If this is a subclass of either fluint class, it creates an instance of the Flunit1ClassRunner.
    • Note, possibility is only checked *if* we are compiled for Flex compatibility. Fluint has Flex dependencies
  • 23. FlexUnit 4 Builder
    • A catch-all for any remaining classes not identified by one of the previous builders
    • Creates an instance of the BlockFlexUnit4ClassRunner()
  • 24. Corrected View with Core
    • The core executes the runner contained within the Request.
    • In this example, the outer most runner would be a Suite class. It would then create a new Suite runner for each of the suites inside. Each of those suites would create a BlockRunner for their test cases and another Suite runner for their contained suite.. Etc.
    Core Request.iRunner (Suite) Suite A Suite B BlockRunner 1 BlockRunner 2 BlockRunner 3 Suite C BlockRunner 7 BlockRunner 8 Tests Tests Tests Tests Tests Request Runner:Suite Test Suite A Test Case 1 Test Test Test Test Test Case 2 Test Test Test Test Test Case 3 Test Test Test Test Test Suite C Test Case 7 Test Case 8 Test Suite B Test Case 4 Test Test Test Test Test Case 5 Test Test Test Test Test Case 6 Test Test Test Test Test Suite D Test Case 9 Test Case 10
  • 25. Output
    • As test run within the FlexUnit 4 runners, we need some way to monitor progress
    • This is accomplished via two types of classes.
    • An implementation of IRunNotifier
    • An implementation of IRunListener
  • 26. IRunNotifier
    • IRunNotifiers are a type of class that FlexUnit 4 uses to notify others of an event that occurred during testing. You can draw parallels with IEventDispatcher
    • IRunNotifiers are used by the IRunner classes to notify others of the following conditions:
    • TestRun: Started/Finished
    • Test: Started/Failed/Ignored/Finished/
    • AssumptionFailures
  • 27. IRunNotifier
    • Unlike an event dispatcher IRunNotifiers have limitations on what types of objects can listen to their events.
    • IRunNotifiers have addListener() and removeListener() methods that accept an IRunListener as an argument
  • 28. IRunListener
    • While there is generally only one IRunNotifier present in the system at any given time, there can be multiple IRunListeners
    • IRunListeners listen to these messages from the notifier and optionally perform some action. Example of IRunNotifiers built into FlexUnit include TraceListener, TextListener, CIListener, XMLListener and others for FlashBuilder integration
  • 29. With Listeners Core Request.iRunner (Suite) Suite A Suite B BlockRunner 1 BlockRunner 2 BlockRunner 3 Suite C BlockRunner 7 BlockRunner 8 Tests Tests Tests Tests Tests UIListener XMLListener CIListener RunNotifier Update a UI Send Data to Server Send Data to Flash Builder Request Runner:Suite Test Suite A Test Case 1 Test Test Test Test Test Case 2 Test Test Test Test Test Case 3 Test Test Test Test Test Suite C Test Case 7 Test Case 8 Test Suite B Test Case 4 Test Test Test Test Test Case 5 Test Test Test Test Test Case 6 Test Test Test Test Test Suite D Test Case 9 Test Case 10
  • 30. Running Tests
    • The BlockFlexUnit4ClassRunner is the heart of running FlexUnit 4 tests.
    • The block runner is responsible for iterating through tests in a given class and executing them
    • While doing this it uses two very important concepts: recursive sequences and decoration
  • 31. Before/Test/After
    • Just to be sure everyone is on the same page FlexUnit 4 has several pieces of Metadata which, when present, control the flow of test execution.
    • These pieces of metadata include BeforeClass, Before, Test, After and AfterClass
    • Multiple methods can be marked by any of these pieces of metadata
  • 32. Before/Test/After
    • BeforeClass
    • Before
    • test1
    • After
    • Before
    • test2
    • After
    • AfterClass
    • [BeforeClass]
    • public static function meFirst():void {
    • }
    • [Before]
    • public function beforeEachTest():void {
    • }
    • [Test]
    • public function test1():void {
    • }
    • [Test]
    • public function test2():void {
    • }
    • [After]
    • public function afterEachTest():void {
    • }
    • [AfterClass]
    • public static function afterEverything():void {
    • }
  • 33. First Sequence
    • BeforeClass
    • Actual Test Class
    • AfterClass
    • Sequences are managed by a class called a StatementSequencer internal to FlexUnit 4
    • Sequences are responsible for ensuring that step 1 finishes before step 2, etc.
    • The first sequence in this example is BeforeClass, ActualTestClass, AfterClass
  • 34. Second Sequence
    • test1
    • test2
    • Sequences can also have entire additional sequence as steps
    • For example, in our last set of steps, we listed Actual Test Class as a step.
    • Running the Actual Test Class, however, means sequencing through each child to execute it
  • 35. Third Sequence
    • Before Sequence
    • test1
    • After Sequence
    • Executing an actual test, requires that we run any methods marked Before, the test, then any methods marked After
    • However, multiple methods can actually be marked Before or After
    • So, in reality, the Before and After calls are actually sequences themselves with a test in the middle
  • 36. Reality
    • Before Class Sequence
    • BeforeClass 1..n
    • Test Class Sequence
    • Test 1 Sequence
      • Before Sequence
      • Before 1..n
      • Test
      • After Sequence
      • After 1..n
    • Test 2 Sequence
      • Before Sequence
      • Before 1..n
      • Test
      • After Sequence
      • After 1..n
    • After Class Sequence
    • AfterClass 1..n
    • Sequences (and the StatementSequencer) are so important because there are thousands of sequences in even a moderately complication test suite
    • In our simple two test example here, we use at least 10
  • 37. Why?
    • The reason we go through all of this trouble with sequencer is that we simply can’t run methods in order
    • We have two things going against us, frames and lack of threads.
    • If anything async has to happen… EVER.. We can no longer rely on method completion to act as an indication that we can move forward
  • 38. Tokens
    • To handle some of this async nature, we use a concept called an AsyncTestToken
    • A token is simply a small object that is passed around the testing system. Object A passes a token to Object B when Object B has work to do. When Object B is done with its work, it notifies Object A by calling a method on this token
  • 39. Tokens
    • This allows every operation and every runner to be potentially asynchronous. Further, it keeps very recursive items decoupled
    • It also has great implications for future support of multiple security domains, etc.
  • 40. Decoration
    • Sequencers are used for every operation that might be potentially asynchronous
    • Decoration are the second concept I mentioned; Decorations are used to ‘wrap’ the invocation of a method with code that should be executed before or after the method, synchronously
  • 41. Wrapping
    • var statement:IAsyncStatement = methodInvoker( method, test );
    • statement = withPotentialAsync( method, test, statement );
    • statement = withPotentialTimeout( method, test, statement );
    • statement = possiblyExpectingExceptions( method, test, statement );
    • statement = withStackManagement( method, test, statement );
    Stack Management Expecting Exception Potential Timeout Potential Async Method Invoker Potential Async Potential Timeout Expecting Exception Stack Management Stack Management Expecting Exception Potential Timeout Potential Async Method Invoker
  • 42. Why?
    • This actually enhances performance and extensibility. Each of these level independently checks the test to see if it is needed
    • If it is not, it acts as a noop. If the layer is needed, for example, we specify async, the logic for that layer is instantiated and enabled to ensure the test is handled properly
  • 43. Stack And Frame
    • The stack and frame management decorator implements green threading to deal with flash frames
    • It tracks how much time in each frame we have used up. When we get close to the end of a frame, we defer the test until the next frame to ensure we never timeout or lock the player during testing
  • 44. Exception
    • The expecting exception decorator implements logic to catch exceptions thrown during the test.
    • If the user indicates that they are expecting an exception then this code compares any thrown exception against the specified one. If they match, all is good. If they don’t or the test doesn’t throw an exception, then this decorator causes the test to fail
  • 45. Potential Timeout
    • The potential timeout decorator implements a timer to ensure the test fails if it exceeds the specified number of milliseconds.
  • 46. Potential Async
    • The potential async decorator creates the infrastructure to monitor an asynchronous test.
    • As this infrastructure carries overhead, we only create it when the user specifics a given test is asynchronous
  • 47. Method Invoker
    • The method invoker actually executes the test method and captures any errors that occur during the method invocation
  • 48. Resources
    • Flex Unit 4!
    • http://opensource.adobe.com/wiki/display/flexunit/FlexUnit
    • Labriola’s Blog
    • http://blogs.digitalprimates.net/codeSlinger/
    • Follow us on twitter
    • mlabriola and flexunit