<p>Ok, I think it does what I want, although I'm waiting on new db permissions to completely test it...</p>
<p>I found <a href="https://stackoverflow.com/a/58011482/13843935">some information on using <code>.runsettings</code></a>, but I couldn't use the MSTest attributes, because the compiler only allows one initialization, which <a href="https://stackoverflow.com/a/58927636/13843935">SpecFlow uses under the hood</a>. I found <a href="https://docs.specflow.org/projects/specflow/en/latest/Bindings/ScenarioContext.html#migrating-from-scenariocontext-current" rel="nofollow noreferrer">SF docs</a> to grab the context surrounding the test, but I had to annotate the class and the setter method with <code>[Binding]</code> and <code>[BeforeScenario]</code>, respectively, which the docs didn't mention.</p>
<p>For anybody interested in the details, I created a <code>.runsettings</code> file in my solution directory with empty values:</p>
<pre class="lang-xml prettyprint-override"><code>&lt;RunSettings&gt;
  &lt;TestRunParameters&gt;
    &lt;Parameter name=&quot;api_token&quot; value=&quot;&quot; /&gt;
    &lt;Parameter name=&quot;password&quot; value=&quot;&quot; /&gt;
  &lt;/TestRunParameters&gt;
&lt;/RunSettings&gt;
</code></pre>
<p>And added to my <code>.csproj</code> file:</p>
<pre class="lang-xml prettyprint-override"><code>  &lt;PropertyGroup&gt;
    &lt;RunSettingsFilePath&gt;$(MSBuildProjectDirectory)\..\.runsettings&lt;/RunSettingsFilePath&gt;
  &lt;/PropertyGroup&gt;
</code></pre>
<p>And in ADO, I edited the <strong>Visual Studio Test</strong> task, setting new params in <strong>Execution options &gt; Override test run parameters</strong>:</p>
<pre><code>-api_token: $(token) -password: $(password)
</code></pre>
<p>And wrote a C# class to get the values:</p>
<pre class="lang-csharp prettyprint-override"><code>using Microsoft.VisualStudo.TestTools.UnitTesting;
using TechTalk.SpecFlow;

namespace UITests
{
    [Binding]
    public class Context
    {
        private static TestContext testContext;

        [BeforeScenario]
        private static void SetContext(ScenarioContext scenarioContext)
        {
            testContext = scenarioContext.ScenarioContainer.Resolve&lt;TestContext&gt;();
        }

        public static string GetSecret(string key)
        {
            if (testContext.Properties.Contains(key))
            {
                return testContext.Properties[key].ToString();
            }
            return null;
        }
    }
}
</code></pre>
<p>Using that class, the I can get the DevOps secrets from that <code>testContext.Properties</code> dictionary, after they overrode the empty values in my <code>.runsettings</code> file.</p>

CC BY-SA 4.0
2022-01-13T22:30:51.927Z
2022-01-13T22:30:51.927Z
Jeremy Meadows
<p>I have a SpecFlow test suite running some Selenium UI tests for our web app in ADO, and we need to access some sensitive information to be able to log in to various places. They are currently stored in normal environment variables so they are in plain text and pretty easy to access, but too insecure to stay that way (it is currently a test user on a dev box, but that will change when the tests are production ready).</p>
<p>ADO secret env vars are not automatically set up in a way that an executable can access, and it does not look like I can pass parameters through <code>vstest.exe</code> to the individual tests.</p>
<p>I suggested something like <code>Azure Key Vault</code>, but that is not an option. I also got <code>dotnet user-secrets</code> working locally, but setting that up on all the agents is apparently not an option either.</p>
<p>I think that secret environment variables should be the way to go, but I am using .NET Framework 4.6.1 and all of the documentation I read to set those up with some sort of config file are for v5+ or Core. If anybody has experience dealing with this, any ideas would help!</p>
<p>Update: I found out it is supposedly possible to use a <code>.runsettings</code> file with empty parameters, and set them from within ADO, but it seems like setting the MSTest attributes conflicts with some of the SpecFlow stuff I need.</p>

CC BY-SA 4.0
2022-01-11T19:22:16.693Z
Can I ask why you can't use Key Vault? It's exactly the right tool for the job
Vince Bowdren
CC BY-SA 4.0
2022-01-11T20:34:26.860Z
@VinceBowdren I'm not sure, I had asked my supervisor and he ruled against it. We are fully in the Microsoft ecosystem, so it really would be something good for them to set up.
Jeremy Meadows
CC BY-SA 4.0
2022-01-12T00:35:14.540Z
another place to securely store secrets is [Azure App Configuration](https://docs.microsoft.com/en-us/azure/azure-app-configuration/overview), but your supervisor may decide against that for the same reason as key vault, whatever that is.
Vince Bowdren
<azure-devops><azure-pipelines><dotnet>
access secret Azure DevOps environment variables in SpecFlow tests
Jeremy Meadows
# access secret Azure DevOps environment variables in SpecFlow tests

(Asked by: username_0 on 2022-01-10)

I have a SpecFlow test suite running some Selenium UI tests for our web app in ADO, and we need to access some sensitive information to be able to log in to various places. They are currently stored in normal environment variables so they are in plain text and pretty easy to access, but too insecure to stay that way (it is currently a test user on a dev box, but that will change when the tests are production ready).

ADO secret env vars are not automatically set up in a way that an executable can access, and it does not look like I can pass parameters through `vstest.exe` to the individual tests.

I suggested something like `Azure Key Vault`, but that is not an option. I also got `dotnet user-secrets` working locally, but setting that up on all the agents is apparently not an option either.

I think that secret environment variables should be the way to go, but I am using .NET Framework 4.6.1 and all of the documentation I read to set those up with some sort of config file are for v5+ or Core. If anybody has experience dealing with this, any ideas would help!

Update: I found out it is supposedly possible to use a `.runsettings` file with empty parameters, and set them from within ADO, but it seems like setting the MSTest attributes conflicts with some of the SpecFlow stuff I need.

**Tags:** azure-devops, azure-pipelines, dotnet

> **Comments:**
> **username_1**: Can I ask why you can't use Key Vault? It's exactly the right tool for the job  
> **username_0**: @VinceBowdren I'm not sure, I had asked my supervisor and he ruled against it. We are fully in the Microsoft ecosystem, so it really would be something good for them to set up.  
> **username_1**: another place to securely store secrets is [Azure App Configuration](https://docs.microsoft.com/en-us/azure/azure-app-configuration/overview), but your supervisor may decide against that for the same reason as key vault, whatever that is.  

---

## 1 answers

### Answer by username_0 on 2022-01-13. Score: 0 | Accepted answer

Ok, I think it does what I want, although I'm waiting on new db permissions to completely test it...
I found some information on using .runsettings, but I couldn't use the MSTest attributes, because the compiler only allows one initialization, which SpecFlow uses under the hood. I found SF docs to grab the context surrounding the test, but I had to annotate the class and the setter method with [Binding] and [BeforeScenario], respectively, which the docs didn't mention.
For anybody interested in the details, I created a .runsettings file in my solution directory with empty values:

  
    
    
  


And added to my .csproj file:
  
    $(MSBuildProjectDirectory)\..\.runsettings
  

And in ADO, I edited the Visual Studio Test task, setting new params in Execution options > Override test run parameters:
-api_token: $(token) -password: $(password)

And wrote a C# class to get the values:
using Microsoft.VisualStudo.TestTools.UnitTesting;
using TechTalk.SpecFlow;

namespace UITests
{
    [Binding]
    public class Context
    {
        private static TestContext testContext;

        [BeforeScenario]
        private static void SetContext(ScenarioContext scenarioContext)
        {
            testContext = scenarioContext.ScenarioContainer.Resolve();
        }

        public static string GetSecret(string key)
        {
            if (testContext.Properties.Contains(key))
            {
                return testContext.Properties[key].ToString();
            }
            return null;
        }
    }
}

Using that class, the I can get the DevOps secrets from that testContext.Properties dictionary, after they overrode the empty values in my .runsettings file.


---

