Similar to sorting the Request class is also responsible for applying filtering of [TestCases]. The filter generated by the Request, by default, simply returns all tests. You must set the filter using the method filterWith and passing it a class of that implements IDescription or is of type IFilter.

IDescription Filtering

Building off the runMe method created in the Request section example, we will now set a filter on our Request using an IDescription.

     public function runMe():void {
          var myRequest : Request;
          //Setting my variable to the Request object return from classes();              
          myRequest = Request.classes( SampleSuite, SampleTest1 ); 

          //applying a filter
          myRequest.filterWith( new Description( unitTests::SampleTest1.test_getName  ) );

          core = new FlexUnitCore();
          //Listener for the UI
          core.addListener( new UIListener( uiListener ));
          core.run( myRequest );
     }

If a new object of type Description with it's displayName set is passed into a request's filterWith method, the tests run within that request will not be filtered if their displayName matches. The displayName should be equal to the getQualifiedClassName( YourClass ) + '.' + NameOfTest. Which is formatted as Package::Class.MethodName . Only one test should be found and run in the end.

IFilter Filtering

In the case that you wish to filter more than one test, which is probably more often the case, you will need to use object that implements IFilter. We will start with a code snippet of AbstractFilter class to help understand the IFilter interface.

     public class AbstractFilter implements IFilter {
          
          public function shouldRun(description:IDescription):Boolean {
               return false;
          }

          public function describe(description:IDescription):String {
               return null;
          }
     
          /**
          * Invoke with a <code> org.flexunit.runner.IRunner</code> to cause all tests it intends to run
          * to first be checked with the filter. Only those that pass the filter will be run.
          * @param child the runner to be filtered by the receiver
          * @throws NoTestsRemainException if the receiver removes all tests
          */
          public function apply( child:Object ):void {
               if (!(child is IFilterable ))
                    return;
               
                var filterable:IFilterable = IFilterable( child );
                filterable.filter(this);
          }
          
          public function AbstractFilter() {
          }
          
     }

This class is used as a base for all the default filters implemented in the framework currently. It is suggested that you extend from AbstractFilter when you're implementing your own Filter since all the interface methods are already implemented for you. Most useful in the implementation is apply() which confirms that your test class has a filter() method and calls it. For the most part apply() can remain how it is by default, you will only need to override the describe() : String and the shouldRun() : Boolean methods.

     /**
     * Returns a textual description of this Filter
     */
     public function describe(description:IDescription):String {
          return null;
     }

*override describe to provide a string description of what the filter does.

     /**
     * Returns true if the test is determined to run otherwise return false.
     */        
     public function shouldRun(description:IDescription):Boolean {
          return false;
     }

*override shouldRun to establish if the given Description object should be run with this filter. Every class at ever level (Suite, Test Class, Theory, Test Method, etc) will pass a description to this shouldRun() method, so it is up to you to decide how you want to handle each and be sure you don't remove a [Suite] when your desire is to run a specific Test Method inside that suite because it won't end up running. The AbstractFilter by default will return false, so every Description passed to it will automatically stop the test from running until you override the method and add your own logic.

[myFilter]

Included Filters

Dynamic Filter

The most customizable of the filter classes provided. The DynamicFilter allows you to define your own shouldRun and describe functions and then pass them into the constructor to be used when the Filter is created.

     public class DynamicFilter extends AbstractFilter {
          private var _shouldRunFunction:Function;
          private var _describeFunction:Function;

          /**
          * @param description the description of the test to be run
          * @return <code>true</code> if the test should be run
          */
          override public function shouldRun( description:IDescription ):Boolean {
               return _shouldRunFunction( description );
          }
          
         /**
         * Returns a textual description of this Filter
         * @return a textual description of this Filter
         */
         override public function describe( description:IDescription ):String {
              return _describeFunction( description );           
         }

         public function DynamicFilter( shouldRunFunction:Function, describeFunction:Function ) {
              if ( ( shouldRunFunction == null ) || ( describeFunction == null ) ) {
                   throw new TypeError("Must provide functions for comparison and description to Filter");
              }
              this._shouldRunFunction = shouldRunFunction;
              this._describeFunction = describeFunction;
         }
     }

IncludeAll Filter

The default filter used by FlexUnit4. If no filter is assigned to your Request when your tests are run the IncludeAll filter is used. I'm sure it isn't difficult to guess what this filter does, it simply runs everything. The shouldRun method always returns true and the describe method indicates the filter is running "all tests".

     public class IncludeAllFilter extends AbstractFilter {
          override public function shouldRun(description:IDescription) : Boolean {
               return true;
          }
          
          override public function describe(description:IDescription) : String {
               return "all tests";
          }

          public function IncludeAllFilter() {
               super();
          }
     }

MethodName Filter

This filter is used to select Test Methods by their literal string names and run them if they match any names in an array passed into the filter. Because every IDescription of every Class you're running gets passed in, the first if-statement is necessary to prevent any Suites, Theories, or Test Cases from being filter by name and keep it exclusive to testing only Test Methods.

     public class MethodNameFilter extends AbstractFilter {
          private var methodNames:Array;

          override public function shouldRun(description:IDescription) : Boolean {
               var methodName:String = "";
     
               if ( !description.isTest ) {
                    //We are only interested in filtering out method names with this filter
                    return true;
               }
               
               if ( description && description.displayName ) {
                    var namePieces:Array = description.displayName.split( '.' );
                    if ( namePieces && namePieces.length > 1 ) {
                         methodName = namePieces[namePieces.length-1];
                    }
               }
               
               return ( methodNames.indexOf( methodName ) != -1 );              
          }
          
          override public function describe(description:IDescription) : String {
               return "Matching method list.";
          }
          
          public function MethodNameFilter( methodNames:Array ) {
               super();
               
               if ( methodNames == null ) {
                    throw new TypeError( "You must provide an array of Method Names to the MethodNameFilter" );
               }
               this.methodNames = methodNames;
          }
     }

  • No labels