Как создать прокси-объект, который перенаправляет вызовы методов в C #? - PullRequest
3 голосов
/ 13 июня 2011

Я пытаюсь использовать селен для запуска тестов; Похоже, что нет хорошего способа запустить один и тот же набор модульных тестов в нескольких браузерах.

Я прочитал этот пост о параллельном запуске тестов: http://slmoloch.blogspot.com/2009/12/design-of-selenium-tests-for-aspnet_19.html

Однако я использую фреймворк для визуального студийного тестирования.

Я могу создать прокси-класс следующим образом:

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);
        }
    }
    ...
}

Мой вопрос такой? Как я могу сделать это без необходимости переписывать весь класс как прокси?

Я подумал, может быть, передавая лямду для отображения аргументов, или передавая функцию, которая принимает имя вызываемого метода, но все они кажутся довольно неубедительными идеями.

Что я действительно хочу, так это добавить члена как:

public class SeleniumProxy {
    public dynamic proxy;
    ....
}

И вызвать это как:

var selenium = getProxy();
selenium.proxy.Open("...");

Разрешает ли c # такой синтаксис для динамических объектов?

Или какой-нибудь мета-обработчик для классов, который позволяет им перехватывать исключения, не связанные с такими методами, и обрабатывать их вручную?

В основном: Как я могу создать прокси-объект, который динамически вызывает методы для внутреннего члена класса?

(Изменить: возможно ... используя отражение в объекте DefaultSelenium и создавая функциональные заглушки в динамическом прокси-объекте для каждой записи ..?)

Ответы [ 2 ]

0 голосов
/ 15 июня 2011

Вы можете использовать наследование и определить свои тесты в абстрактном базовом классе с помощью фабричного метода для создания экземпляра селена, а затем наследовать его для каждого типа браузера, который хотите моделировать.Затем тесты будут выполняться для каждого унаследованного класса с соответствующим браузером.Используя 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");
    }
}
0 голосов
/ 15 июня 2011

Если я понимаю, что вы пытаетесь сделать, я думаю, вы можете расширить 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 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...