Creating a behavior

Behaviors all derive from the base SpecsFor.Behavior class. For a behavior that will apply to all specs, TType will be ISpecs, the non-generic interface that all specs implement. Here's our LogExecutionTimeBehavior:

using SpecsFor;
using SpecsFor.Configuration;

namespace Conventions.Basics
{
    public class LogExecutionTimeBehavior : Behavior<ISpecs>
    {
    }
}

You can override virtual methods from the base Behavior class in order to define logic that should be executed during a spec's execution. The available methods are:

  • SpecInit - Executed once SpecsFor's auto-mocking container has initialized.
  • ClassUnderTestInitialized - Executed once the System Under Test has been instantiated.
  • Given - Executed before the spec's Given method is executed. This is a great place to apply state across specs.
  • AfterSpec - Executed after the spec's AfterSpecs method has been executed. You can hook in here to do cleanup, if necessary.

For our behavior, we'll want to capture the time between when the spec is initialized (SpecInit) and when it ends (AfterSpec). We can do that using the Stopwatch class:

public class LogExecutionTimeBehavior : Behavior<ISpecs>
    {
        private Stopwatch _stopwatch;

        public override void SpecInit(ISpecs instance)
        {
            _stopwatch = Stopwatch.StartNew();
        }

        public override void AfterSpec(ISpecs instance)
        {
            _stopwatch.Stop();

            Console.WriteLine($"{instance.GetType().Name} - {_stopwatch.Elapsed}");
        }
    }

Now when we run our specs, our behavior will output the execution time for each one.

1167

Admittedly, this isn't the most-useful behavior. Let's look at something a little more useful.

Continue on to defining state with a behavior