Setups & Cleanups
SpecK offers various levels to specify setup and cleanup code:
Since setups and cleanups represent a unit, SpecK guarantees meaningful execution of them in case of exceptions. A typical setup scenario could look like this:
-
Bootstrap.Setup
SuiteSetup1.Setup
-
SuiteSetup2.Setup
CaseSetup.Setup
<Tests>
CaseSetup.Cleanup
SuiteSetup2.Cleanup
SuiteSetup1.Cleanup
DatabaseBootstrap.Cleanup
Since Setup1
and Setup2
are on the same level, they will be executed in nested order. If Setup2
throws an exception for some reason, the execution will immediately continue with the execution of the cleanup of Setup1
; so the cleanup of Setup2
is skipped.
By inheriting from IAssemblySetup
you can create setup/cleanup logic that is executed once for all test suites in an assembly that require the setup:
public class DatabaseAssemblySetup : IAssemblySetup
{
DbContext Context;
public void Setup () { /* create connection */ }
public void Cleanup () { /* close connection */ }
}
public class MySpec : Spec
{
[AssemblySetup] DatabaseAssemblySetup DatabaseAssemblySetup;
}
Because the outcome of assembly setups is crucial, SpecK injects them into test suites. Note that assembly setups are only executed if they are imported by at least one test suite. It is advisable to create a base class, if many test suites depend on the same bootstrap.
On suite-level you can use SetupOnce
to execute the code only once for all test cases:
public class MySpec : Spec
{
MySpec()
{
SetupOnce (setup: CreateDatabase, cleanup: DropDatabase);
SetupOnce (setup: CreateTables, cleanup: DropTables);
}
}
The execution is defined as CreateDatabase, CreateTables, <Tests>, DropTables, DropDatabase
With Setup
you can declare setup and cleanup code that is execute for each case:
public class MySpec : Spec<DomainType>
{
MySpec()
{
Setup (SetupSubjectInstance, CleanupSubjectInstance);
}
void SetupSubject(ITestContext<DomainType> context) { }
void CleanupSubject(ITestContext<DomainType> context) { }
}
In this case, the execution will be SetupSubject, <Test1>, CleanupSubject
, then SetupSubject, <Test2>, CleanupSubject
and so on.
Note that if you use the automated subject creation facilities, you will be able to access the subject instance from within the setup and cleanup methods.
For individual setups and cleanups, you can use the various GivenUsing
overloads:
public class MySpec : Spec
{
MySpec()
{
Specify (x => Foo.Bar())
.DefaultCase (_ => _
.GivenUsing (new CultureContext ("en-US"))
.Given ("custom arrangement", x => { })
.GivenUsing (setup: SetupStuff, cleanup: CleanupStuff))
.It ("assertion", x => { }));
}
public class CultureContext : IDisposable
{
public CultureContext (string culture) { /* save old and set new culture */ }
public void Dispose() { /* restore old culture */ }
}
}
As mentioned before, the execution engine will skip cleanups if their related setups were not successful. Usage can also be extended into much cleaner calls like GivenUsingCulture ("en-US")
.