cze
6
2012
.NET // WatiN

WatiN - nie zamykanie przeglądarki po każdym teście

W poprzednim poście napisałem, że ostatecznie jako rozwiązanie do testów automatycznych Web w naszym systemie wybrałem WaiN. Zacząłem więc pisać testy i od razu uwidocznił się pierwszy problem. Otóż standardowy wzorzec zakłada odpalenie przeglądarki, zrobienie testu i jej zamknięcie czyli:

using (var browser = new IE("http://perszewski.pl"))
                {
                    // Rób test
                }

W przypadku większej ilości testów każdorazowe odpalanie IE i jego zamykanie zaczyna znacząco wydłużać czas testów. Pasowało więc wymyśleć sposób na to, żeby przeglądarkę odpalić przy pierwszym teście a zamknąć po ostatnim. Rozwiązanie udało się opracować a zacząłem od stworzenia klasy statycznej, która będzie trzymała referencję do mojej przeglądarki:

public static class TestObjectBuilder
{
    private static IE _browser;

public static IE Browser
        {
            get
            {
                if (_browser == null)
                {
                    _browser = new IE();
                }
                return _browser;
            }
        }

Wydaje się, że to wystarczy ale niestety nie działa :) Ponieważ poszczególne testy odpalane są w różnych wątkach to próba dostępu do zmiennej _browser z następnego testu po pierwszym kończy się rzuceniem wyjątku. Należało ten fragment kodu zmodyfikować w sposób następujący:

public static class TestObjectBuilder
    {
        private static IE _browser;
        private static string _ieHwnd;
        private static int _ieThread;

public static IE Browser
        {
            get
            {
                if (_browser == null)
                {
                    _browser = new IE();
                    _ieHwnd = _browser.hWnd.ToString();
                    _ieThread = Thread.CurrentThread.ManagedThreadId;
                }
                if (Thread.CurrentThread.ManagedThreadId != _ieThread)
                {
                    _browser = IE.AttachTo<IE>(Find.By("hwnd", _ieHwnd));
                    _ieThread = Thread.CurrentThread.ManagedThreadId;
                }
                return _browser;
            }
        }
}

Tym razem poza referencją do obiektu przeglądarki trzymam również identyfikator wątku w którym została utworzona a także uchwyt jej okna. W przypadku próby dostępu z innego wątku niż ten, w którym została stworzona następuje podpięcie pod istniejący wątek (WatiN udostępnia przydatną metodę AttachTo) i aktualizacja identyfikatora wątku. Wykorzystanie tej metody jest już proste, w każdym teście na początku jest otrzymywany obiekt typu IE w ten sposób:

IE browser = TestObjectBuilder.Browser;

Testy nie martwią się cyklem życia tego obiektu, tylko go wykorzystują. 

Po wykonaniu wszystkich testów pasuje zamknąć otwartą cały czas przeglądarkę. Jest to realizowane przez kolejną metodę statyczną:

public static void CleanUp()
        {
                var p = Process.GetProcessesByName("iexplore").Where(w => w.MainWindowHandle.ToString() == _ieHwnd).FirstOrDefault();
                if (p != null)
                {
                    p.Kill();
                }
        }

Jak widać sposób jest brutalny ale skuteczny :) Wołanie CleanUp następuje w klasie bazowej testów:

[AssemblyCleanup]
        public static void CleanUp()
        {
            TestObjectBuilder.CleanUp();
        }

Opisane metody działały w naszym przypadku bez zarzutu, nie było problemów z odpaleniem czy też zamknięciem IE. W następnym odcinku powiem jak udało się poradzić z nieszczęściem Pop-Upów :)