OneTimesetup is getting invoked for each Test,I thought OneTimesetup is like BeforeSuite,TestNG annotation

3k views Asked by At

In Nunit C# Im trying to open the application only once and make modification to it, for example i created this demo of Notepad application. In my real time project,i just have to log in to the application just once and execute all 100 test cases and only then close the Desktop application. Kindly tell me what am i doing wrong here,thanks a lot! Btw,im new to C#

using NUnit.Framework;
using OpenQA.Selenium.Remote;
using System;
using OpenQA.Selenium;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace Notepad
{ }
    [SetUpFixture]
    public class BaseClass

    {
        public static IWebDriver driver;

        [OneTimeSetUp]
        public static void AssemblyInitalize()
        {
            var dc = new DesiredCapabilities();
            dc.SetCapability("app", @"C:\\Windows\\System32\\notepad.exe");
            driver = new RemoteWebDriver(new Uri("http://localhost:9999"), dc);
            Thread.Sleep(5000);
        }

        [OneTimeTearDown]
        public static void oneTearDown()
        {
            driver.FindElement(By.Id("Close")).Click();

        }
    }

---First Test---

namespace Notepad
{    [TestFixture]
    public class Notepad2:BaseClass
    {

        [Test]
     public void test2()
        {
            driver.FindElement(By.Id("15")).SendKeys("My Teacher ");
        }

    }
}

---- Second Test Class ----

 using NUnit.Framework;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using OpenQA.Selenium;

    namespace Notepad 
    {    [TestFixture]
      public  class NoteTest : BaseClass

        {


            [Test]
            public void Test()
            {

                driver.FindElement(By.Id("15")).SendKeys("...is Coming now");
            }
        }
    }
2

There are 2 answers

6
Charlie On

Regarding SetUpFixture, the first answer is incorrect.

SetUpFixture works exactly the same way as it has always worked. If you have a SetUpFixture, it's OneTimeSetUp and OneTimeTearDown methods will run once for all the fixtures under the same namespace.

On the other hand, inside a TestFixture the OneTimeSetUp and OneTimeTearDown methods run just once for the fixture itself.

In other words, the methods run "one time" within the particular scope in which they are used, namespace or fixture.

The problem is that you are using the same class as both a SetUpFixture and as the base class for all your TestFixtures. That means if you have n test fixtures, it will run n + 1 times! That's what you are seeing.

SetUpFixtures do not (have never had) anything to do with fixture inheritance. You should either make your class a SetUpFixture or a TestFixture base class. If, for whatever reason, you need both, then use two classes. In this case, you need only the SetUpFixture, without the inheritance.

When to inherit from a base class: When you want the same code to execute many times, once for each fixture. Note that your base class, when used for one-time setup and teardown in this way, should normally not be marked as a TestFixture.

When to use a SetUpFixture: When you want some code to execute only once, before every any fixture runs and again once after all the fixtures have run.

In your example, you are using a SetUpFixture to control the timing of the initialization. You are using inheritance to allow you to share the driver. Problem is that the OneTimeSetUp in the base class is actually part of each test fixture and you don't want that.

I'd be concerned about a hundred or so tests all using the same driver. I've seen some people use one driver per test and others one driver per fixture_. Using one for __everything implies that you are being extraordinarily careful that each test cleans up after itself and restores the driver to the same state. I doubt that's possible.

However, as an exercise, here is how to do it if you really want to: 1. Have a base class with nothing but the driver member. 2. Derive the SetUpFixture from the base class and create / destroy the driver there. 3. Derive the TestFixtures from the same base class. They use but don't change the driver.

5
iakobski On

From the documentation, OneTimeSetup is called once before all tests in a TestFixture. Your example has two fixtures, so the set up is called twice. You need to have all your tests in the same Fixture.

This behaviour is different to the old [Setup] on SetupFixture attribute, which ran once for all tests in a namespace.