I've been back working with BizTalk 2006 R2 for a customer recently and I've become such a fan of the BDD style acceptance tests I've done in the past with BizTalk 2010 that its quite frustrating working back in Visual Studio 2005 and not being able to use Specflow alongside BizUnit 4 like I described in the recent videos on these subjects
In BizTalk 2006 development your back to the older style xml bizunit tests and we were looking at some old tests written a long time ago and frankly it's hard to remember what they were supposed to do. This is where the separation between intention and implementation of the test is so important. Since there isn't a great deal we can do about this in terms of upgrading the technology we took the very simple approach of annotating the BizUnit tests using the Gherkin style so that before each test step or group of test steps there was something to explain what was intended to happen. The other benefit is it really encourages the TDD approach.
In the first example below you can see when writing a new test we have simply used the Gherkin syntax Given/When/Then to record the requirements and definition of what needs to happen in this test.
<TestCase testName="VAU.CardChanges">
<TestSetup>
<!-- GIVEN: The test event queue is clean-->
<!-- GIVEN: The test folder is empty - Acquirer folders -->
<!-- GIVEN: The test folder is empty - CardSystem folders -->
<!-- GIVEN: The test folder is empty - CRM folders -->
<!-- GIVEN: The acquirer file generation numbers are zero -->
</TestSetup>
<TestExecution>
<!-- WHEN: TWS calls BizTalk to trigger the validation of payments -->
<!-- THEN: The response will indicate that validation has started -->
<!-- THEN: BizTalk will start the batch processing orchestration -->
<!-- THEN: BizTalk will send the batch to the acquirer -->
<!-- THEN: The acquirer will find the batch in their input folder -->
<!-- THEN: The acquirer will put the response in their output folder -->
<!-- THEN: BizTalk will recieve an acknowledgement from the acquirer -->
<!-- THEN: BizTalk will recieve a response file from the acquirer -->
<!-- THEN: BizTalk will process any card updates -->
<!-- THEN: The card will be updated in CARDSYSTEM-->
<!-- THEN: The validation batch will be updated in CARDSYSTEM-->
<!-- THEN: The card will be updated in CRM-->
<!-- THEN: Biztalk will have completed processing the validation batch response -->
<!-- THEN: The card update received by CRM will be valid -->
<!-- THEN: The card update received by CARDSYSTEM will be valid -->
</TestExecution>
<TestCleanup>
<!—Clean Test Folders -->
</TestCleanup>
</TestCase>
The fully completed and implemented test looks like the below example. Now hopefully you can clearly see how important this simple documentation around the tests are for people who may look at this in the future.
<TestCase testName="VAU.CardChanges">
<TestSetup>
<!-- GIVEN: The test event queue is clean-->
<TestStep
assemblyPath="Acme.CardProcessing.AcceptanceTests.dll"
typeName="Acme.CardProcessing.AcceptanceTests.BizUnitSteps.TestEvents.CleanEvents">
</TestStep>
<!-- GIVEN: The test folder is empty - Acquirer folders -->
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileDeleteMultipleStep">
<Directory>..\..\..\Acme\CardProcessing\Stubs\DropFolders\AcquirerRequest</Directory>
<SearchPattern>*.*</SearchPattern>
</TestStep>
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileDeleteMultipleStep">
<Directory>..\..\..\Acme\CardProcessing\Stubs\DropFolders\AcquirerResponse</Directory>
<SearchPattern>*.*</SearchPattern>
</TestStep>
<!-- GIVEN: The test folder is empty - CardSystem folders -->
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileDeleteMultipleStep">
<Directory>..\..\..\Acme\CardProcessing\Stubs\DropFolders\CardSystemWS</Directory>
<SearchPattern>*.*</SearchPattern>
</TestStep>
<!-- GIVEN: The test folder is empty - CRM folders -->
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileDeleteMultipleStep">
<Directory>..\..\..\Acme\CardProcessing\Stubs\DropFolders\CRMWS</Directory>
<SearchPattern>*.*</SearchPattern>
</TestStep>
<!-- GIVEN: The acquirer file generation numbers are zero -->
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.DBExecuteNonQueryStep">
<DelayBeforeExecution>1</DelayBeforeExecution>
<ConnectionString>Persist Security Info=False;Integrated Security=SSPI;Server=localhost;Database=PaymentCardServices</ConnectionString>
<SQLQuery>
<RawSQLQuery>UPDATE FileNumber SET FileNumber = 1 WHERE ID = 'NextFGN'</RawSQLQuery>
</SQLQuery>
</TestStep>
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.DBExecuteNonQueryStep">
<DelayBeforeExecution>1</DelayBeforeExecution>
<ConnectionString>Persist Security Info=False;Integrated Security=SSPI;Server=localhost;Database=PaymentCardServices</ConnectionString>
<SQLQuery>
<RawSQLQuery>UPDATE FileNumber SET FileNumber = 1 WHERE ID = 'ActiveFGN'</RawSQLQuery>
</SQLQuery>
</TestStep>
</TestSetup>
<TestExecution>
<!-- WHEN: TWS calls BizTalk to trigger the validation of payments -->
<TestStep assemblyPath="Acme.BizTalk.Fx.Testing.dll" typeName="Acme.BizTalk.Fx.Testing.BizUnit.Wse2WebServicesClientProtocolStep">
<WebServiceUrl>http://localhost/Acme.CardProcessing.Secure/CardService.ashx</WebServiceUrl>
<ProxyTypeName>Acme.CardProcessing.Utilities.Testing.TestProxies CardService, Acme.CardProcessing.Utilities</ProxyTypeName>
<ProxyMethodName>SubmitBatchValidation</ProxyMethodName>
<ExpectingError>false</ExpectingError>
<InputMessageTypeName>Acme.CardProcessing.Utilities.Testing.TestProxies.CardValidationBatch, Acme.CardProcessing.Utilities</InputMessageTypeName>
<MessagePayloadPath>..\..\..\Acme.CardProcessing.AcceptanceTests\Features\BatchValidation\TestData\CardChanges.Input.xml</MessagePayloadPath>
<!-- THEN: The response will indicate that validation has started -->
<ValidationStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.XmlValidationStep">
<XPathList>
<XPathValidation query="/ValidationBatchesReturn/Return">0</XPathValidation>
</XPathList>
</ValidationStep>
</TestStep>
<!-- THEN: BizTalk will start the batch processing orchestration -->
<TestStep assemblyPath="Acme.CardProcessing.AcceptanceTests.dll" typeName="Acme.CardProcessing.AcceptanceTests.BizUnitSteps.TestEvents.EventExists">
<Action>Batch validation started</Action>
<RemoveEventFromQueue>true</RemoveEventFromQueue>
<SecondsToWait>30</SecondsToWait>
</TestStep>
<!-- THEN: BizTalk will send the batch to the acquirer -->
<TestStep
assemblyPath="Acme.CardProcessing.AcceptanceTests.dll"
typeName="Acme.CardProcessing.AcceptanceTests.BizUnitSteps.TestEvents.EventExists">
<Action>Batch sent to acquirer</Action>
<RemoveEventFromQueue>true</RemoveEventFromQueue>
<SecondsToWait>30</SecondsToWait>
</TestStep>
<!-- THEN: The acquirer will find the batch in their input folder -->
<TestStep assemblyPath="Acme.BizTalk.Fx.Testing.dll" typeName="Acme.BizTalk.Fx.Testing.BizUnit.FileExistsStep">
<Timeout>60</Timeout>
<DirectoryPath>..\..\..\Acme\CardProcessing\Stubs\DropFolders\AcquirerRequest</DirectoryPath>
<SearchPattern>*.*</SearchPattern>
<ExpectedNoOfFiles>1</ExpectedNoOfFiles>
</TestStep>
<!-- THEN: The acquirer will put the response in their output folder -->
<TestStep assemblyPath="Acme.CardProcessing.AcceptanceTests.dll" typeName="Acme.CardProcessing.AcceptanceTests.BizUnitSteps.ProcessAcquirerFileStep">
<DirectoryPath>..\..\..\Acme\CardProcessing\Stubs\DropFolders\AcquirerRequest</DirectoryPath>
<SearchPattern>INZET.DANG.MDNDMDM</SearchPattern>
<ResponsesXmlFileName>..\..\..\Acme.CardProcessing.AcceptanceTests\GenericTestData\HSBCDefaultBatchResponse.xml</ResponsesXmlFileName>
<SchemaFileName>..\..\..\Acme.CardProcessing.AcceptanceTests\GenericTestData\BatchResponses.xsd</SchemaFileName>
<CreationPath>..\..\..\Acme\CardProcessing\Stubs\DropFolders\AcquirerResponse</CreationPath>
<InvalidResponse></InvalidResponse>
<MultipleResponse>false</MultipleResponse>
</TestStep>
<!-- THEN: BizTalk will recieve an acknowledgement from the acquirer -->
<TestStep
assemblyPath="Acme.CardProcessing.AcceptanceTests.dll"
typeName="Acme.CardProcessing.AcceptanceTests.BizUnitSteps.TestEvents.EventExists">
<Action>Acknowledgement received from acquirer</Action>
<RemoveEventFromQueue>true</RemoveEventFromQueue>
<SecondsToWait>30</SecondsToWait>
</TestStep>
<!-- THEN: BizTalk will recieve a response file from the acquirer -->
<TestStep
assemblyPath="Acme.CardProcessing.AcceptanceTests.dll"
typeName="Acme.CardProcessing.AcceptanceTests.BizUnitSteps.TestEvents.EventExists">
<Action>Acquirer response received</Action>
<RemoveEventFromQueue>true</RemoveEventFromQueue>
<SecondsToWait>30</SecondsToWait>
</TestStep>
<!-- THEN: BizTalk will process any card updates -->
<TestStep
assemblyPath="Acme.CardProcessing.AcceptanceTests.dll"
typeName="Acme.CardProcessing.AcceptanceTests.BizUnitSteps.TestEvents.EventExists">
<Action>Processing card updates</Action>
<RemoveEventFromQueue>true</RemoveEventFromQueue>
<SecondsToWait>30</SecondsToWait>
</TestStep>
<!-- THEN: The card will be updated in CARDSYSTEM-->
<TestStep
assemblyPath="Acme.CardProcessing.AcceptanceTests.dll"
typeName="Acme.CardProcessing.AcceptanceTests.BizUnitSteps.TestEvents.EventExists">
<Action>CardServicesStub.CardServices.UpdatePaymentCards Called</Action>
<RemoveEventFromQueue>true</RemoveEventFromQueue>
<SecondsToWait>30</SecondsToWait>
</TestStep>
<!-- THEN: The validation batch will be updated in CARDSYSTEM-->
<TestStep
assemblyPath="Acme.CardProcessing.AcceptanceTests.dll"
typeName="Acme.CardProcessing.AcceptanceTests.BizUnitSteps.TestEvents.EventExists">
<Action>CardServicesStub.CardServices.UpdateValidationBatch Called</Action>
<RemoveEventFromQueue>true</RemoveEventFromQueue>
<SecondsToWait>30</SecondsToWait>
</TestStep>
<!-- THEN: The card will be updated in CRM-->
<TestStep
assemblyPath="Acme.CardProcessing.AcceptanceTests.dll"
typeName="Acme.CardProcessing.AcceptanceTests.BizUnitSteps.TestEvents.EventExists">
<Action>CRMApplicationStub.FinanceRefService.UpdateCreditCardDetails Called</Action>
<RemoveEventFromQueue>true</RemoveEventFromQueue>
<SecondsToWait>30</SecondsToWait>
</TestStep>
<!-- THEN: Biztalk will have completed processing the validation batch response -->
<TestStep
assemblyPath="Acme.CardProcessing.AcceptanceTests.dll"
typeName="Acme.CardProcessing.AcceptanceTests.BizUnitSteps.TestEvents.EventExists">
<Action>Batch validation completed</Action>
<RemoveEventFromQueue>true</RemoveEventFromQueue>
<SecondsToWait>30</SecondsToWait>
</TestStep>
<!-- THEN: The card update received by CRM will be valid -->
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileValidateStep">
<Timeout>6000</Timeout>
<Directory>..\..\..\Acme\CardProcessing\Stubs\DropFolders\CRMWS</Directory>
<SearchPattern>*.*</SearchPattern>
<DeleteFile>false</DeleteFile>
<ValidationStep assemblyPath="Acme.CardProcessing.Utilities.dll" typeName="Acme.CardProcessing.Utilities.Testing.BizUnit.XmlComparisonValidationStep">
<CompareTo>CardChanges.CRM.UpdateCards.xml</CompareTo>
</ValidationStep>
</TestStep>
<!-- THEN: The card update received by CARDSYSTEM will be valid -->
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileMultiValidateStep">
<Timeout>6000</Timeout>
<DirectoryPath>..\..\..\Acme\CardProcessing\Stubs\DropFolders\CardSystemWS</DirectoryPath>
<SearchPattern>*.*</SearchPattern>
<ValidationStep assemblyPath="Acme.CardProcessing.Utilities.dll" typeName="Acme.CardProcessing.Utilities.Testing.BizUnit.XmlComparisonValidationStep">
<CompareTo>CardChanges.CardSystem.UpdateCards.xml</CompareTo>
</ValidationStep>
<ValidationStep assemblyPath="Acme.CardProcessing.Utilities.dll" typeName="Acme.CardProcessing.Utilities.Testing.BizUnit.XmlComparisonValidationStep">
<CompareTo>CardChanges.UpdateBatch.xml</CompareTo>
</ValidationStep>
</TestStep>
</TestExecution>
<!-- Clear out all test folders -->
<TestCleanup>
<!-- Acquirer folders -->
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileDeleteMultipleStep">
<Directory>..\..\..\Acme\CardProcessing\Stubs\DropFolders\AcquirerRequest</Directory>
<SearchPattern>*.*</SearchPattern>
</TestStep>
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileDeleteMultipleStep">
<Directory>..\..\..\Acme\CardProcessing\Stubs\DropFolders\AcquirerResponse</Directory>
<SearchPattern>*.*</SearchPattern>
</TestStep>
<!—Card App folders -->
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileDeleteMultipleStep">
<Directory>..\..\..\Acme\CardProcessing\Stubs\DropFolders\CardSystemWS</Directory>
<SearchPattern>*.*</SearchPattern>
</TestStep>
<!-- CRM folders -->
<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileDeleteMultipleStep">
<Directory>..\..\..\Acme\CardProcessing\Stubs\DropFolders\CRMWS</Directory>
<SearchPattern>*.*</SearchPattern>
</TestStep>
</TestCleanup>
</TestCase>