PowerShell, Pester and Gherkin - Testing for Multiple Acceptable Values

Viewed 233

I'm trying to write some tests using PowerShell, Pester and Gherkin but I'm struggling to work out how I can test against multiple values.

For example, I could use Get-Service to check the status of a Windows service. If I want to check if it is running, I could say:

When I check my service
Then the status is "Running"

OK, nice and simple. What I really want to be able to do is say:

When I check my service
Then the status is "Stopped" or "Disabled"

I could do this by passing multiple parameters to the step file, i.e.

'the status is "(.*)" or "(.*)"'

but I want it to be neater than that and more re-usable - this is just a simple example but for real scenarios I'd have to build a step for one parameter, two, three, etc.

It'd be much nicer to be able to pass them across from the feature file and have a simple step definition. This may not be the 'best' way to do BDD but bear with me.

In my head, what I want to do is pass an array from the feature file with a list of the acceptable values, something like:

When I check my service
Then the status is ""Stopped","Disabled""

and then my step has something like:

'the status is <myarray>'
$actualvalue | Should -BeIn <myarray>

I know this isn't valid code but you get the idea. I tried implementing this idea but couldn't get it to work, I can't pass an array even if I define the parameter as one in the step file.

I also tried looking at Data Tables but I had no luck there either.

Another attempt using Examples also failed - I can make it run each test in turn but not one OR the other.

Does anyone have any suggestions for how this could be best achieved? As I said, ignore the specific example, it's the logic I'm interested in - how to test for one thing OR another thing OR another and if any are true then it's a pass.

1 Answers

Based on your first example, you really only care about the process running or not. Instead of describing implementation details in the scenario, focus on the main business process: the service is running or stopped.

From a behavior driven development perspective, you gain nothing with a parameterized step. From a development perspective, you are better off with separate step definitions simply because "stopped" could be "Stopped" or "Disabled". Stopped, from a business perspective, is one of two different statuses. Either one satisfies the test.

Asserting that a service is running is just one status. This deserves its own step definition for the same reason you would code two different functions to start and stop a service. This is further reinforced by your business domain, which is PowerShell running on Windows. The Start-Process and Stop-Process commandlets in PowerShell are separate for a reason. To me, this justifies two step definitions. Parameterizing this step will just increase the complexity of the step itself for no real gain.

I would even go one step further and forego any mention of "status" and just imply state what it should be:

When I check my service
Then my service should be running

For the other scenario, I would do something similar:

When I check my service
Then my service should not be running

The end user (the PowerShell user) just cares about the service running or not. The step asserting that the service is not running will know to check for "Stopped" or "Disabled" statuses, and it should fail otherwise.

Other scenarios that do care about a specific status could be their own step. If you just need to check for a single status, then a parameterized step works, because the assertion is generalized:

Scenario: Stopping my service
    Given my service was started
    And I stopped my service
    When I check my service
    Then my service should be "Stopped"

Scenario: Disabling my service while it is running
    Given my service was started
    And I disabled my service
    When I check my service
    Then my service should be "Disabled"

Scenario: Disabling my service after it was stopped
    Given my service was started
    And I stopped my service
    And I disabled my service
    When I check my service
    Then my service should be "Disabled"
Related