Create test run with state property in Azure DevOps .NET SDK - c#

I'm using the Azure DevOps .NET SDK (v16.530.0-preview) and when I try to create a test run using CreateTestRunAsync (in TestManagementHttpClient) and use the RunCreateModel object as a parameter, it looks like the RunCreateModel's State property is read-only. The docs also confirm this.
TestApi.RunCreateModel run = new TestApi.RunCreateModel
{
Name = testRun.Name
//State = testRun.State (is read-only)
};
https://learn.microsoft.com/en-us/dotnet/api/microsoft.teamfoundation.testmanagement.webapi.runcreatemodel.state?view=azure-devops-dotnet-preview#Microsoft_TeamFoundation_TestManagement_WebApi_RunCreateModel_State
But the weirdness is that when creating the run, the UI shows In Progress then it shows the test run running for {x hours, minutes, sec}.
Is there a way I can avoid this and set the state as NotStarted?

You can define the state in the constructor:
var testRun = new RunCreateModel(name: "API Test Run", state: "NotStarted");
var results = testApi.CreateTestAsync(testRun, "Project").Result;
I succeeded to create a test run with "Not Started" state with the above code.

Related

Update Build Pipeline variables from .Net code

We have a build definition i Azure DevOps that creates a docker image and pushes it to Azure Container Registry. The definition has a pipeline variable that has to be inserted at build time. I have to queue the build from my .Net code. I can get the definition but don't see how to update the pipeline variable.
VssBasicCredential credentials = new VssBasicCredential("",persAccToken);
VssConnection connection = new VssConnection(uri, credentials);
BuildHttpClient buildClient = connection.GetClient<BuildHttpClient>();
BuildDefinition def = buildClient.GetDefinitionAsync(projectName, definitionId).Result;
The pipeline variable is "settable at queue time". However I don't find a way to do it from my code.
BuildDefinition has property Variables that contains pipeline variables. That variable can be removed and than added with new value or updated
BuildDefinitionVariable bdv = new BuildDefinitionVariable { AllowOverride = true,
IsSecret = false, Value = "new-vaule" };
def.Variables.Remove("variable-name");
def.Variables.Add("variable-name", bdv);
buildClient.UpdateDefinitionAsync(def, projectName, def.Id);
Update Build Pipeline variables from .Net code
As workaround, you can update a variable value by emitting the following with Powershell scripts:
"##vso[task.setvariable variable=testvar;]testvalue"
Check the document Logging Commands for some more details.
Then you could call this .ps1 with your .Net code.
Hope this helps.

How to set ManagedBy property for Security Group via C#

I am having issues updating the ManagedBy property for Security Groups (works fine for Distribution Groups). I receive the following error: '{"You don't have sufficient permissions. This operation can only be performed by a manager of the group."}'
I am running with an account that has full access. The command works when running via PowerShell just not via C#. Here is the command I am running.
Command cmdCreateDR = new Command("Set-DistributionGroup");
cmdCreateDR.Parameters.Add("Identity", "GroupName");
cmdCreateDR.Parameters.Add(new CommandParameter("BypassSecurityGroupManagerCheck"));
Collection<PSObject> manByUsers = new Collection<PSObject>();
manByUsers.Add(new PSObject("domain\\UserName1"));
manByUsers.Add(new PSObject("domain\\UserName2"));
cmdCreateDR.Parameters.Add("ManagedBy", manByUsers);
Collection<PSObject> resultsEx = RunPowerShellCommand(cmdCreateDR);
BypassSecuirtyGroupManagerCheck is a switch and the way your using it your passing it in a bool set to false which won't achieve your desired results. You should be doing something like
SwitchParameter switchpara = new SwitchParameter(true);
cmdCreateDR.Parameters.Add("BypassSecurityGroupManagerCheck", switchpara);
Cheers
Glen

Updating from Selenium.Webdriver 2.44 to 2.46 causes NullReferenceException

We have just started working with Appium in my company, using it to automate testing on websites and webapps.
Testing Framework = Nunit 2.6.4
Language used = C#
Mobile Device = Samsung Galaxy S4
Android version = 5.0.1
I've used Selenium and Nunit to test on Desktop before on a simple website, using [Test], [TestCase] and [TestCaseSource] attributes in my tests.
Following the advice in the article of the answer to:
How to integrate Appium with C#?
(Quicker article link here:
http://blogs.technet.com/b/antino/archive/2014/09/22/how-to-set-up-a-basic-working-appium-test-environment.aspx)
An associate set up a solution that would do a simple navigation to StackOverflow, click a link and assert:
namespace AppiumTests
{
using System;
using NUnit.Framework;
using AppiumTests.Helpers;
using AppiumTest.Framework;
using OpenQA.Selenium; /* Appium is based on Selenium, we need to include it */
using OpenQA.Selenium.Appium; /* This is Appium */
using OpenQA.Selenium.Appium.Interfaces; /* Not needed for commands shown here. It might be needed in single tests for automation */
using OpenQA.Selenium.Appium.MultiTouch; /* Not needed for commands shown here. It might be needed in single tests for automation */
using OpenQA.Selenium.Interactions; /* Not needed for commands shown here. It might be needed in single tests for automation */
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Appium.Android;
[TestFixture]
public class AndroidAppiumTestSuite
{
private AppiumDriver driver;
private static Uri testServerAddress = new Uri(TestServers.WindowsServer);
private static TimeSpan INIT_TIMEOUT_SEC = TimeSpan.FromSeconds(180); /* Change this to a more reasonable value */
private static TimeSpan IMPLICIT_TIMEOUT_SEC = TimeSpan.FromSeconds(10); /* Change this to a more reasonable value */
[SetUp]
public void BeforeAll()
{
DesiredCapabilities capabilities = new DesiredCapabilities();
TestCapabilities testCapabilities = new TestCapabilities();
//testCapabilities.App = "";
testCapabilities.AutoWebView = true;
testCapabilities.AutomationName = "<just a name>";
testCapabilities.BrowserName = "Chrome"; // Leave empty otherwise you test on browsers
testCapabilities.DeviceName = "Needed if testing on IOS on a specific device. This will be the UDID";
testCapabilities.FwkVersion = "1.0"; // Not really needed
testCapabilities.Platform = TestCapabilities.DevicePlatform.Android; // Or IOS
testCapabilities.PlatformVersion = "5.0.1"; // Not really needed
testCapabilities.AssignAppiumCapabilities(ref capabilities);
driver = new AndroidDriver(testServerAddress, capabilities, INIT_TIMEOUT_SEC);
driver.Manage().Timeouts().ImplicitlyWait(IMPLICIT_TIMEOUT_SEC);
}
[TearDown]
public void AfterAll()
{
TestContext.CurrentContext.Result.ToString();
driver.Quit(); // Always quit, if you don't, next test session will fail
}
/// <summary>
/// Just a simple test to heck out Appium environment.
/// </summary>
[Test]
public void CheckTestEnvironment()
{
driver.Navigate().GoToUrl("http://stackoverflow.com");
driver.FindElementByCssSelector("body > div.topbar > div.network-items > div.login-links-container > a").Click();
Assert.AreEqual("Log in using any of the following services", (driver.FindElementByCssSelector("h2.title")).Text);
}
Many thanks to Andrea Tino for this starting point.
Now this worked fine, and my colleague who set this up and showed it to me has gone on holiday leaving me the task of adding in our existing tests and tweaking bits here and there.
I added in my testclass which requires the Webdriver.Support pacakge to be installed, which depends on Webdriver >= 2.46.0
Now, when I run my code, I get a null reference exception on this line:
driver = new AndroidDriver(testServerAddress, capabilities, INIT_TIMEOUT_SEC);
This is the error I'm getting:
AppiumTests.AndroidAppiumTestSuite.CheckTestEnvironment:
SetUp : System.NullReferenceException : Object reference not set to an instance of an object.
TearDown : System.NullReferenceException : Object reference not set to an instance of an object.
So my thought was that something in 2.46.0 meant I need to supply another capability, but I've been banging my head against this for two days now with no progress.
I have a screenshot of the appium server communication, but I'm not able to link images yet XD so here is it pasted in:
info: [debug] Device launched! Ready for commands
info: [debug] Setting command timeout to the default of 60 secs
info: [debug] Appium session started with sessionId 4575272bba7d11c85414d48cf53ac8e3
info: <-- POST /wd/hub/session 303 10828.204 ms - 70
info: --> GET /wd/hub/session/4575272bba7d11c85414d48cf53ac8e3 {}
info: Proxying [GET /wd/hub/session/4575272bba7d11c85414d48cf53ac8e3] to [GET http://127.0.0.1:9515/wd/hub/session/4575272bba7d11c85414d48cf53ac8e3] with body: {}
info: Got response with status 200: {"sessionId":"4575272bba7d11c85414d48cf53ac8e3","status":0,"value":{"acceptSslCerts":true,"applicationCacheEnabled":false,"browserConnectionEnabled":false,"browserName":"chrome","chrome":{},"cssSelect...
info: <-- GET /wd/hub/session/4575272bba7d11c85414d48cf53ac8e3 200 6.770 ms - 506
info: --> POST /wd/hub/session {"desiredCapabilities":{"javascriptEnabled":true,"device":"Android","platformName":"Android","deviceName":"d5cb5478","browserName":"Chrome","platformVersion":"5.0.1","browserVersion":"43.0.2357.93"}}
error: Failed to start an Appium session, err was: Error: Requested a new session but one was in progress
So from here I can see that its trying to start a new session when I've already started one, but I can't figure out the cause!
So here's how to get around the Appium-specific half of the problem -- I don't have an answer for your NullReferenceException.
That Appium error is caused when the port you're trying to start Appium WebDriver on is already in use.
To manually fix this
You can do $telnet ip port to figure out what Process ID you need to kill.
You can find the address/port by checking the value for what new Uri(TestServers.WindowsServer); returns.
Exit any emulators
Once you have the PID then you can do $kill -9 pid and start your Appium server like normal.
A proper solution
If you are having this problem regularly, it may be because your script is ending without quitting the Appium WebDriver.
Usually you put the teardown code for the WebDriver (driver.quit()) in the #After section of your tests, or in your base TestCase class.
I see that you have a teardown section there -- so maybe you got into this bad state during a previous session? Either way, the manual fix should get you back to working order.

How to set CCSID for MQQueueManager from code?

I have some strange problem. I think I followed documentation correctly but my code doesn't work. I have this very simple hard coded test (NUnit):
[TestFixture]
public class MQQueueTests {
public const string MessageContent = "<test>This is test message</test>";
public static void Main(string[] args) {
var tests = new MQQueueTests();
tests.PutAndGetMessage();
}
[Test]
public void PutAndGetMessage() {
var properties = new Hashtable
{
{MQC.HOST_NAME_PROPERTY, "TestServer"},
{MQC.CHANNEL_PROPERTY, "Test.Channel"},
{MQC.PORT_PROPERTY, 1415},
// Is this correct? It looks like it is not
// enough because adding this line didn't solve
// the problem.
{MQC.CCSID_PROPERTY, 437}
};
using (var manager = new MQQueueManager("Test.Queue.Manager", properties)) {
using (MQQueue queue = manager.AccessQueue("Test.Queue",
MQC.MQOO_OUTPUT | MQC.MQOO_INPUT_AS_Q_DEF)) {
MQMessage message = new MQMessage();
message.WriteUTF(MessageContent);
queue.Put(message);
MQMessage readMessage = new MQMessage();
queue.Get(readMessage);
Assert.AreEqual(MessageContent, readMessage.ReadUTF());
queue.Close();
}
manager.Disconnect();
}
}
}
I'm running the test application either from console or through Resharper 6 test runner. If I run the application in test runner I always get following exception:
IBM.WMQ.MQException : MQRC_CHANNEL_CONFIG_ERROR (reason code is 2539)
The exception is thrown by MQQueueManager.Connect (called by its constructor).
If I check MQ logs I see:
AMQ9541: CCSID supplied for data conversion not supported.
EXPLANATION: The program ended because, either the source CCSID '437'
or the target CCSID '852' is not valid, or is not currently supported.
ACTION: Correct the CCSID that is not valid, or ensure that the
requested CCSID can be supported.
If I run the application from the console I got the same error but if I change the code page for console by calling
chcp 437
My test application works. How can I configure code page from code?
Well I found a workaround - it can probably solve my problem but I'm not very satisfied with it. I can set up MQCCSID environment variable either globally or by calling:
Environment.SetEnvironmentVariable("MQCCSID", "437");
That will configure code page. Still I would like to use properties of a new MQQueueManager instance to setup code page.
Both of these are answers correct. For Windows Forms Project setting the environment variable MQCCSID the same as the ccsid of the Queue Manager that you are trying to connect will be enough.
- the 2nd solution
HKEY_LOCAL_MACHINE->SYSTEM->CurrentControlSet->Control->Nls->CodePage>OEMCP value.
i had a web application(web forms) that only worked with the 2nd solution
change your system locale to English(United States), on windows 7 Regional Settings -> Administrative->Change System locale. also after do that you can check it in regedit value.
regedit->HKEY_LOCAL_MACHINE->SYSTEM->CurrentControlSet->Control->Nls->CodePage check OEMCP value.

Changing how a service is configured

When installing a service, there is a helpful .NET class called ServiceProcessInstaller. This class has a property Account, which is a ServiceAccount enumeration with possible values LocalService, LocalSystem, NetworkService and User.
This is fine at install-time, but does anybody know how I can change this value for an existing service?
I assuming that I need to move away from the actual install-type classes, and have been researching hooking into the advapi32 ChangeServiceConfig method, WMI and ManagementObjects etc.
Indeed I have found code which will actually change the account under which the service runs,
ManagementObject mo = new ManagementObject("Win32_Service.Name='" + myService + "'");
object[] configParams = new object[11];
configParams[6] = userName;
configParams[7] = password;
object result = mo.InvokeMethod("Change", configParams);
(which on its own looks a bit like black magic but makes sense when viewed with the ChangeServiceConfig signature)
However when I apply this code to a service which happens to be installed as LocalSystem, it has no effect (although when I interpret result the call is reporting success). This doesn't really surprise me since I am only setting a username and password, I am not saying "rather than running as a local service, this service needs to run under a specific user account".
Now, my gut feel is that I am heading along the right lines here. The problem is that none of the parameters in ChangeServiceConfig appear to offer the opportunity to do this.
Any ideas? TIA, Pete
Error code 16 means "Service marked for deletion". Sometimes when you change service parameter, in particular when you delete / re-create a service you need to reboot your PC for operation to complete. While it's still pending, you can't manipulate service and you get error code 16.
Also, it might not be the case, that you problem has something to do with the fact that the call is inside a dll. If you put you code in a test rig dll and call it from a test rig exe (the same way you tested it in a test rig exe) and don't create / delete service in between I think it will work anyway.
The reason it does not working in your application on my opinion has to do with what you did with the service before (and this something most likely is not described in your question).
You need Impersonate an thread to run at context of user.
Try this class :
A small C# Class for impersonating a User
or this one :
Impersonate User
Return code is 21: "Invalid Parameter".
I ran into the same issue: Problem occurs when trying to apply a new user/password to a service which currently has "LocalSystem" with "Allow Service to interact with desktop" enabled.
To resolve, set the "DesktopInteract" flag in the "Change" query
var query = new ManagementPath(string.Format("Win32_Service.Name='{0}'", serviceName)); // string.Format("SELECT * FROM Win32_Service where Name='{0}'", serviceName);
using (ManagementObject service = new ManagementObject(query))
{
object[] wmiParams = new object[10];
//WMI update doesn't work if the service's user is currently set to LocalSystem
// with Interact with desktop on
wmiParams[5] = false;
wmiParams[6] = serviceUserName;
wmiParams[7] = password;
//update credentials for the service
var rtn = service.InvokeMethod("Change", wmiParams);
}

Categories