Magenic / MAQS

Magenic's automation quick start
MIT License
45 stars 18 forks source link

Multiple drivers in one test #500

Closed JameyRandall closed 3 years ago

JameyRandall commented 4 years ago

MAQS 6.0.1 Custom SAP Driver built based on 6.0.1 SAPBusinessUnit.Tests.UI.E2E.Combo.ScreenSHot - 2020-09-25-06-01-06-4727.txt SAPScreenshot

I am trying to use two drivers in one test a custom driver and a selenium driver. I am finding that that screen shots are only attached from the selenium driver. The screen shots for the custom driver are not taken at soft assert fail. I can force a screen shot to be taken of the custom driver, but it ill not get attached.

If I run a test that uses just the custom driver I am getting screen shots as expected.

I am thinking the issues is that I am not hitting the BeforeLoggingTeardown() for the custom driver since my inheritance for the test class follows the Selenium route. I know C# does not support inheriting from 2 different classes at once.

Do you have a recommendation as to how I can hit the BeforeLoggingTeardown for both of my drivers and test objects? Or do you think this might be a different issue?

[TestMethod]
        public void ScreenShot()
        {

            LoginPageModel login = new LoginPageModel(TestObject);
            NavigationPageModel nav = login.LogIntoSAPFiori(Logins.InternalSalesRepresentativeGL);
            SoftAssert.IsTrue(false, "Assert fail");

            //Setup SAP Gui Test Object use existing Selen Log
            SAPBaseTest sapBaseTest = new SAPBaseTest();
            SAPTestObject SAPObject = new SAPTestObject(() => sapBaseTest.GetClient(), TestObject.Log, GetFullyQualifiedTestClassName());
            //Gui Test
            SapGuiLogin guiLogin = new SapGuiLogin(SAPObject);
            NavigationPage guiNav = guiLogin.CompleteLoginScreen();
            //take screen shot of gui          
            SAPObject.SoftAssert.IsTrue(false, "Screen Shot Test");
            //Force screen shot
            SAPUtilities.CaptureScreenshot(SAPObject, "GUI");

            SoftAssert.FailTestIfAssertFailed();
        }
JameyRandall commented 4 years ago

I was able to get it to work adding in a TestCleanup with the following code. But since the file names are all the same and in the same location. Shouldn't either the selenium or custom clean up attach all files with the same name as the log file?

[TestCleanup]
        public async Task TestCleanup()
        {
            if(TestObjectSAP.DriverManager.IsDriverIntialized())
            {
                if (TestObjectSAP.SoftAssert.DidSoftAssertsFail())
                {
                    SAPUtilities.CaptureScreenshot(TestObjectSAP, " Gui");
                }

                foreach (string path in TestObjectSAP.GetArrayOfAssociatedFiles())
                {
                    if(File.Exists(path))
                    {
                        TestContext.AddResultFile(path);
                    }
                }

            }
TroyWalshProf commented 4 years ago

My guess is that you are creating separate test objects.
This works, but requires you to do some extra work. - Like what you have done Ideally you only want one test object per test.

What you likely want to do is leverage the manager store: https://magenic.github.io/MAQS/#/MAQS_6/General/ManagerStore

For real code examples see: https://github.com/Magenic/MAQS/tree/master/Framework/CompositeUnitTests

FermJacob commented 4 years ago

@JameyRandall Could you provide the whole test class? Interested to see the class inheritance and the test initialize.

JameyRandall commented 4 years ago
public class HybridBaseTest : BaseSeleniumTest
    {
        public APITestBase testBase = new APITestBase();
        public BaseTestCaseObject testCase = new BaseTestCaseObject();
        public SAPTestObject TestObjectSAP;

        [TestInitialize]

        public void TestInitialize()
        {
            SAPBaseTest sAPBase = new SAPBaseTest();
            TestObjectSAP = new SAPTestObject(() => sAPBase.GetClient(), TestObject.Log, GetFullyQualifiedTestClassName());
        }

        /// <summary>
        /// Take GUI screenshot if Gui soft assert failed
        /// report overall test outcome to SolMan
        /// </summary>
        /// <returns></returns>
        [TestCleanup]
        public async Task TestCleanup()
        {
            if(TestObjectSAP.DriverManager.IsDriverIntialized())
            {
                if (TestObjectSAP.SoftAssert.DidSoftAssertsFail())
                {
                    SAPUtilities.CaptureScreenshot(TestObjectSAP, " Gui");
                }

                foreach (string path in TestObjectSAP.GetArrayOfAssociatedFiles())
                {
                    if(File.Exists(path))
                    {
                        TestContext.AddResultFile(path);
                    }
                }

            }

            //API call to SolMan for testcase update
            if (TestContext.CurrentTestOutcome == UnitTestOutcome.Passed)
            {
                await testBase.Results(APITestBase.TestResults.Pass,
                    testCase.testCaseId,
                    testCase.testPackageId,
                    testCase.testExecutionId,
                    testCase.testRunId);
            }
            else
            {
                await testBase.Results(APITestBase.TestResults.Fail,
                    testCase.testCaseId,
                    testCase.testPackageId,
                    testCase.testExecutionId,
                    testCase.testRunId);
            }

        }

        /// <summary>
        /// object for Testcase params
        /// </summary>
        public class BaseTestCaseObject
        {
            public BaseTestCaseObject() { }
            public string testCaseId { get; set; }
            public string testPackageId { get; set; }
            public string testExecutionId { get; set; }
            public string testRunId { get; set; }
            public string testStepId { get; set; }
        }
    }
JameyRandall commented 4 years ago

I see when adding a driver you use WebDriverFactory.GetBrowserWithDefaultConfiguration(BrowserType.HeadlessChrome) in most of the tests. Can I pull values from appconfig and use a remote browser with the manage store? I dont see an obvious method that will do this. Browser = Remote, RemoteBrwoser = Chrome

FermJacob commented 4 years ago

You would want to utilize the ManagerStore for your SAP driver because you are inheriting from BaseSeleniumTest.

Here are a few examples:

this.ManagerStore.Add("WebServiceDriver", new WebServiceDriverManager(() =>
            {
                var client = new HttpClient { BaseAddress = {UriOfUrl}};
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", {BearerToken});
                return client;
            }, this.TestObject));
this.ManagerStore.Add("DatabaseToUse", new DatabaseDriverManager(() => DatabaseConfig.GetOpenConnection("SQLSERVER", {SQL Server Connection String}), this.TestObject));

It would then be utilized by

var driver = this.ManagerStore.GetDriver<EventFiringWebServiceDriver>("WebServiceDriver");
var dbDriver = this.ManagerStore.GetDriver<DatabaseDriver>("DatabaseToUse");
JameyRandall commented 4 years ago

Thanks,

I have been able to add the SAPdriver to the manage store, I am now hitting issues with the test objects. Since the SAPTestObject and the SeleniumTestObject are different (one uses guiSession one has IWebDriver), I am looking at trying to build a custom test object that supports both. I am then hoping I can pass the HybridObject into the constructor for both the Selenium and the SAP page models.

I might be falling down the rabbit hole though since the test cleanup solution I put together does ultimately log and take a final screen shot of the gui.

TroyWalshProf commented 4 years ago

All test objects are capable of being hybrid objects.

Each test object has a ManagerStore. The ManagerStore can contain N number of DriverManagers. You can add as many DriverManagers (and DriverManagers types) as you want.

You may be getting confused because the use of "this.ManagerStore" this.ManagerStore is actually this.TestObject.ManagerStore, we just provide a shorter way to get to it. Example of what this means:

// These are all basically the same call  
IWebDriver seleniumDriver = this.TestObject.ManagerStore.GetDriver<IWebDriver, SeleniumDriverManager>();  
seleniumDriver = this.TestObject.WebDriver;   
seleniumDriver = this.WebDriver;  

So what you can do is just add the SAP driver in setup and use it in your page object model later: Using the Selenium test object with an unnamed SAP driver:

// Add in your test setup
this.TestObject.AddDriverManager(new SAPDriverManager(() => SAPDriverMAKE(), this.TestObject));

// Get the SAP driver out of the test object
SAPDriver sapDriver = this.TestObject.ManagerStore.GetDriver<SAPDriver, SAPDriverManager>();
IWebDriver seleniumDriver = this.TestObject.WebDriver;

Using the Selenium test object with an named SAP driver:

// Add as a named driver in your test setup
this.TestObject.ManagerStore.Add("SAP", new SAPDriverManager(() => SAPDriverMAKE(), this.TestObject));

// Get the named SAP driver out of the test object
SAPDriver sapDriver = this.TestObject.ManagerStore.GetDriver<WebServiceDriver>("SAP")
IWebDriver seleniumDriver = this.TestObject.WebDriver;
FermJacob commented 4 years ago

@JameyRandall Were you able to solve the issue?

JameyRandall commented 4 years ago

I am out on PTO. I plan to take a look at it when I get back next week.

-Jamey Randall

On Oct 5, 2020, at 10:25 AM, Jacob Ferm notifications@github.com wrote:

 @JameyRandall Were you able to solve the issue?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

FermJacob commented 4 years ago

Hi @JameyRandall,

Were you able to solve the issue?

JameyRandall commented 4 years ago

@FermJacob

I am still having issues with the test object. When I call the login page for SAP it is expecting an SAPTestObject which it inherits from the GuiBasePage in our SAP package.

GUILoginPageModel guiLogin = new GUILoginPageModel(TestObjectSAP);

public class GUILoginPageModel : GUIBasePage {

    public GUILoginPageModel(SAPTestObject testObject) : base(testObject)
    {
        _elements = new Elements();
    }
  ...

}

I tried what Troy had suggested but my GUI page models cannot take the SeleniumTestObject that the SAPdriver is now attached to.

JameyRandall commented 3 years ago

Going to close this for now. At this time we are keeping GUI and Fiori testing separate.