Skip to content

Extending Crm.Specflow

Martijn Vermaat edited this page Oct 28, 2022 · 9 revisions

Introduction

You can extend this library with your own code if needed. Below are some parts that you can customize with your own project specific requirements

Writing your own steps

Writing your own steps works the same way as any SpecFlow step. There are however 2 considerations to take into account.

Context Classes

CrmTestingContext

Obtain an instance of this class by using dependency injection in your specflow binding class. To do that simply add the CrmTestingContext to the constructor of your class. You will get a seperate instance per scenario.

  • CommandProcessor: When executing commands, go through this object. It will make sure your step will be executed correctly.
  • RecordBuilder: Here you can build Entity objects using default values or based on its parent record using attribute mappings
  • RecordCache: All the records that have an alias are stored in this object
  • TableConverter: This object will convert the SpecFlow table at runtime. It changes the display to logical names and allows custom logic. See more information below.
  • Targets: This is the list targets based on your srprofile targets.

SeleniumTestingContext

This object has information used for UI testing only. Here you can get information like the current App or Browser type. Also use this object when you want to obtain the correct browser instance.

GlobalTestingContext

This object has global variables that are valid throughout the entire test run. Use this object to get Metadata and the current CRM API connection.

Use Commands

If you write your own steps, it is recommended to create your actions as commands. This way you don't have to worry about checking whether your action should run via the API or via the user interface. There are 3 types of commands (see table below). Each of the commands have two variations. One with and one without return value (like Action and Func).

Command API Testing UI Testing
APIOnlyCommand Runs via API Runs via API
BrowserCommand Runs via API Runs via UI
BrowserOnlyCommand Exception Runs via UI

Modifying the table at runtime

The steps that have a 'Table' parameter will go through the 'ConvertTable' method in the TableBuilder. You can find the instance in the CrmContext. This TableConverter has 4 events you can register to. It will call the events in the following order:

  1. (Before first row) OnTableProcessed
  2. (Per Row) OnRowProcessing
  3. (Per row) OnRowProcessed
  4. (After last row) OnTableProcessed

Role based implementation

To implement multiple users, you can call the GlobalTestingContext.ConnectionManager.SetCurrentConnection & GlobalTestingContext.ConnectionManager.SetAdminConnection. These methods are called before every scenario and set to the default.

Formulas

Install the Vermaat.Crm.Specflow.Expressions package and you are good to go. As a value you can now write '={expression}'. To add new expressions, you can get the 'FormulaContext' and call the 'AddFunctionType'.

Using hooks to set the model app at runtime

At the start of each scenario the app is defaulted to the value is the app.config (Key = AppName). You can change the app via the 'SeleniumTestingContext.CurrentApp' property. In example you can create a hook that runs BeforeScenario to change the app based on tags.

Error Codes

All custom exceptions that are thrown are of type 'TestExecutionException' All of these exceptions have an error code. You can add your own error codes via the 'ErrorCodes.AddError' method. This class uses the 'String.Format' method, so you can add parameters that way.

Selenium Commands

Each piece of browser interaction will over time be done by Selenium Commands. Each command is for 1 specific function, like saving or clicking a ribbon button. These commands are created by a 'SeleniumCommandFactory'. You can override the methods if you want to change the command.