#c# #unit-testing #selenium
#c# #модульное тестирование #selenium
Вопрос:
Я пытаюсь использовать selenium для запуска тестов; похоже, что нет хорошего способа запустить один и тот же набор модульных тестов в нескольких браузерах.
Я прочитал этот пост о параллельном выполнении тестов: http://slmoloch.blogspot.com/2009/12/design-of-selenium-tests-for-aspnet_19.html
Однако я использую платформу модульного тестирования Visual studio.
Я могу создать прокси-класс, подобный этому:
public class SeleniumProxy {
private List<DefaultSelenium> targets;
public SeleniumProxy() {
targets = new List<DefaultSelenium>();
targets.Add(new DefaultSelenium(... "firefox"...));
targets.Add(new DefaultSelenium(... "iexplore"...));
}
public void Open(String url) {
foreach (var i in targets) {
i.Open(url);
}
}
...
}
Мой вопрос заключается в следующем? Как я могу это сделать, не переписывая весь класс в качестве прокси?
Я подумал, может быть, передать lamda в аргументы map или передать функцию, которая принимает имя вызываемого метода, но все это кажется довольно неубедительными идеями.
Чего я действительно хочу, так это добавить элемент, подобный:
public class SeleniumProxy {
public dynamic proxy;
....
}
И вызвать это следующим образом:
var selenium = getProxy();
selenium.proxy.Open("...");
Допускает ли c # такой синтаксис для динамических объектов?
Или какой-то мета-обработчик для классов, который позволяет им перехватывать исключения, не относящиеся к такому методу, и обрабатывать их вручную?
В принципе: как я могу создать прокси-объект, который динамически вызывает методы для внутреннего члена класса?
(Редактировать: возможно … используя отражение в объекте DefaultSelenium и создавая заглушки функций в динамическом прокси-объекте для каждой записи ..?)
Комментарии:
1. На вашем месте я бы снова заглянул в Selenium Grid, он довольно продвинутый. По моему опыту, тестирование IE Selenium занимает в 5-10 раз больше времени, чем FF, поэтому, если вы попытаетесь запускать тесты параллельно по-своему, ваши тесты FF также будут длиться вечно.
2. На самом деле не имеет значения, займет ли это больше времени; вам все равно придется подождать IE.
Ответ №1:
Если я понимаю, что вы пытаетесь, я думаю, вы можете расширить DynamicObject для достижения этой цели.
class Proxy : System.Dynamic.DynamicObject
{
public Proxy(object someWrappedObject) { ... }
public override bool TryInvokeMember(System.Dynamic.InvokeMemberBinder binder, object[] args, out object result)
{
// Do whatever, binder.Name will be the called method name
}
}
//Do whatever...
стал бы некоторым кодом, который обращается к внутренним элементам какого-либо другого объекта (предположительно, посредством отражения), используя binder.Name
как часть процесса поиска.
Существуют TryGetMember
и TryGetIndex
методы, которые можно переопределить, если вам нужно обернуть что-нибудь более причудливое, что вызывает простой метод.
Вам придется приводить экземпляры Proxy
в dynamic
после построения, чтобы выполнять произвольные вызовы, точно так же, как при работе с ExpandoObject.
Ответ №2:
Вы могли бы использовать наследование и определить свои тесты в абстрактном базовом классе с фабричным методом для создания вашего экземпляра selenium, а затем наследовать это для каждого типа браузера, который вы хотите смоделировать. Затем тесты будут выполняться для каждого унаследованного класса с помощью соответствующего браузера. Используя NUnit в качестве примера:
public abstract class AbstractTests
{
protected abstract DefaultSelenium CreateSelenium();
[Test]
public void TestSomethingA()
{
DefaulSelenium selenium = CreateSelenium();
//Do some testing with selenium.
}
}
[TestFixture]
public class IETests : AbstractTests
{
protected override DefaultSelenium CreateSelenium()
{
return new DefaultSelenium("iexplore");
}
}
[TestFixture]
public class FirefoxTests : AbstractTests
{
protected override DefaultSelenium CreateSelenium()
{
return new DefaultSelenium("firefox");
}
}