Фреймворк для тестирования сервиса.
От: Sharov Россия  
Дата: 22.01.13 10:07
Оценка:
Всем здравствуйте.

Имеется некий WCF сервис, который хотелось бы протестировать интеграционными тестами.

Создал небольшую простенькую программку следующего содержания:

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

-- сценарии состоят из отельных шагов (step), т.е. по сути своей шаг -- это некий класс-обертка над методом сервиса: авторизация пользователя,
удаление чего-либо и т.д.

Сценарий реализует интерфейс
public interface IScenario
{
  bool Prepare();

  bool Execute();

  bool Validate();

  void Clean();

  string FailDescription { get; }
}


Шаг реализует интерфейс:

public interface IExecuteStep
{
  bool ExecuteStep();
}



Ну далее создается сценарий, в него добавляются некоторые шаги, все это дело отрабатывает, проверяется результат.

Если кто сталкивался с подобными задачами, то, пожалуйста, поделитесь опытом, советами, полезными ссылками.

Заранее благодарю.
Кодом людям нужно помогать!
Re: Фреймворк для тестирования сервиса.
От: . Великобритания  
Дата: 22.01.13 13:15
Оценка:
Здравствуйте, Sharov, Вы писали:

S> -- имеются классы сценариев, которые представляют собой реальные сценарии взаимодействия с сервисом, например, завести пользователя,

Слово "сценарий" сразу мне напоминает о BDD. Посмотри в сторону NAct, xBehave, xSpec или подобного. Да вообще погугли ".NET BDD".
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[2]: Фреймворк для тестирования сервиса.
От: Sharov Россия  
Дата: 22.01.13 15:04
Оценка:
Здравствуйте, ., Вы писали:

Про BDD слышал. Т.е. мне необходимо боевое тестирование сервиса, со всеми side-effect'ами и прочим.
Интересовал сам подход к тому, как это лучше осуществить. Может кто сталкивался или использовал какие-нибудь
фреймворки для интеграционных и необязательно тестов. Все что я видел, либо платное, либо не очень
продвинутое (soapUI, например).
Кодом людям нужно помогать!
Re[3]: Фреймворк для тестирования сервиса.
От: . Великобритания  
Дата: 22.01.13 18:44
Оценка: +1
Здравствуйте, Sharov, Вы писали:

S>Здравствуйте, ., Вы писали:


S>Про BDD слышал. Т.е. мне необходимо боевое тестирование сервиса, со всеми side-effect'ами и прочим.

S>Интересовал сам подход к тому, как это лучше осуществить. Может кто сталкивался или использовал какие-нибудь
S>фреймворки для интеграционных и необязательно тестов. Все что я видел, либо платное, либо не очень
S>продвинутое (soapUI, например).
Я бы для сервиса (SOAP?) генерил клиентский стаб из wsdl и тупо писал бы тесты:
@Test
void testUserRegistration()
{
  User user = theService.registerUser("vasya");
  assert vasya.getName() == "vasya";
}

И это дело бы деплоилось и выполнялось в тестовом окружении CI сервером.
В общем мне не понятен конкретный вопрос. JFDI.
Что ты ожидаешь от фреймворка?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[3]: Фреймворк для тестирования сервиса.
От: Aikin Беларусь kavaleu.ru
Дата: 23.01.13 07:53
Оценка:
Здравствуйте, Sharov, Вы писали:


S>Т.е. мне необходимо боевое тестирование сервиса, со всеми side-effect'ами и прочим.

S>Интересовал сам подход к тому, как это лучше осуществить.
Мне вот тоже непонятно что именно спрашивается. Если специализированный тул конкретно для сервисов, то причем тут C# и интерфейсы? Неужели специализированный тул будет заточен как раз под твои нужды?

А самое главное, почему бы не сгенерить клиента к этому сервису (как советует <b>.</b>
Автор: .
Дата: 22.01.13
), а далее уже использовать любой из инструментов тестирования (а уж в них прикрутить IScenario и проч. не сставит труда).

Я именно так и тестирую свои сервисы. Только я не тестировал сам WCF сервис, я напрямую создавал объект сервиса в коде (благо WCF позволяет это) и вызывл его через его интерфейс.

СУВ, Aikin
... << RSDN@Home 1.2.0 alpha 5 rev. 1539>>
Re[4]: Фреймворк для тестирования сервиса.
От: Sharov Россия  
Дата: 23.01.13 09:12
Оценка:
Здравствуйте, ., Вы писали:

.>Что ты ожидаешь от фреймворка?


Очень виноват, т.к. некорректно сформулировал вопрос. Задача -- боевое тестривание (интеграционное) WCF сервиса.
Сгенерировал клиентов как положено и т.д. и т.п. Теперь просто хочу написать, по сути уже написал, небольшую программулину
для тестирования и организовал сл. образом: имеются классы сценариев (см. выше) и классы шагов (по сути обертки над функциями сервиса).
Ну и далее пишу сценарии из этих простейших шагов и валидирую результат. Вопрос был больше покритиковать мой подход, сценарии и шаги,
поделиться опытом. Наверняка кто-то с подобными задачами сталкивался.
Кодом людям нужно помогать!
Re[4]: Фреймворк для тестирования сервиса.
От: Sharov Россия  
Дата: 23.01.13 09:18
Оценка:
Здравствуйте, Aikin, Вы писали:


A>Мне вот тоже непонятно что именно спрашивается. Если специализированный тул конкретно для сервисов, то причем тут C# и интерфейсы? Неужели специализированный тул будет заточен как раз под твои нужды?


Специализированный и обобщенный тул не нужен, только если посмотреть на сам подход к вопросу. Свой собственный тул уже написал.

A>А самое главное, почему бы не сгенерить клиента к этому сервису (как советует <b>.</b>
Автор: .
Дата: 22.01.13
), а далее уже использовать любой из инструментов тестирования (а уж в них прикрутить IScenario и проч. не сставит труда).


Так и сделал.

A>Я именно так и тестирую свои сервисы. Только я не тестировал сам WCF сервис, я напрямую создавал объект сервиса в коде (благо WCF позволяет это) и вызывл его через его интерфейс.


Вы не могли бы подробнее? Т.е. Вы просто локально тестировали какой-то сервисный объект, без удаленного взаимодействия?
Кодом людям нужно помогать!
Re[5]: Фреймворк для тестирования сервиса.
От: . Великобритания  
Дата: 23.01.13 09:44
Оценка: 3 (1)
Здравствуйте, Sharov, Вы писали:

.>>Что ты ожидаешь от фреймворка?

S>Очень виноват, т.к. некорректно сформулировал вопрос. Задача -- боевое тестривание (интеграционное) WCF сервиса.
S>Сгенерировал клиентов как положено и т.д. и т.п. Теперь просто хочу написать, по сути уже написал, небольшую программулину
S>для тестирования и организовал сл. образом: имеются классы сценариев (см. выше) и классы шагов (по сути обертки над функциями сервиса).
S>Ну и далее пишу сценарии из этих простейших шагов и валидирую результат. Вопрос был больше покритиковать мой подход, сценарии и шаги,
S>поделиться опытом. Наверняка кто-то с подобными задачами сталкивался.
Можно пример? Просто непонятно зачем тут эти интерфейсы, зачем вводить понятие "сценарий", "шаг" и т.п.? Чем обычный тест-кейс формата arrange/act/assert плох?
А ещё закрадывается подозрение, если без обёрток сервис использовать неудобно, значит что-то не то с его API.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: Фреймворк для тестирования сервиса.
От: Sharov Россия  
Дата: 23.01.13 10:32
Оценка:
Здравствуйте, ., Вы писали:

.>Можно пример? Просто непонятно зачем тут эти интерфейсы, зачем вводить понятие "сценарий", "шаг" и т.п.?


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


Сценарий выглядит как то так. На строковые константы внимание не обращайте.
[Scenario("User creation scenario.", Order = 1)]
    public class CreateUserScenario : IScenario
    {
        private string _credentials;
        private string _failDescription;

        #region IScenario Members

        public string FailDescription
        {
            get { return _failDescription; }
        }

        public bool Prepare()
        {
            _credentials = ScnHelper.GenerateTestUserCredentials();
            return true;
        }

        public bool Execute()
        {
            using (Client Client = new Client())
            {
                var authorize = new AuthorizeUserStep(Client, "test","test").ExecuteStep();
                if (!authorize)
                {
                    _failDescription = "Execute stage. " + "Administrator is not properly authorized";
                    return false;
                }

                var create = new CreateUserStep(Client, _credentials, _credentials, false).ExecuteStep();
                if (create < 1)
                {
                    _failDescription = "Execute stage. " + "User was not created properly";
                    return false;
                }
                return true;
            }
        }

        public bool Validate()
        {
            using (Client Client = new Client())
            {
                var authorize = new AuthorizeUserStep(Client, "test","test").ExecuteStep();
                if (!authorize)
                {
                    _failDescription = "Validate stage. " + " Administrator is not properly authorized";
                    return false;
                }

                var check = Utils.CheckUserStep(Client, _credentials, ref _failDescription);
                if (!check)
                {
                    _failDescription = "Validate stage. " + "Created user checking return false.";
                    return false;
                }
                return true;
            }
        }

        public void Clean()
        {
            using (var Client = new Client())
            {
                var authorize = new AuthorizeUserStep(Client, "test", "test").ExecuteStep();

                if (!authorize)
                {
                    _failDescription = "Clean stage. " + "Administrator is not properly authorized";
                    return;
                }

                var result = new DeleteUserStep(Client, _credentials).ExecuteStep();
                if (!result)
                {
                    _failDescription = "Clean stage. " + "User was not deleted properly.";
                }
            }
        }

        #endregion
    }


PS. Прощу прощения, а как вставлять скрытый текст? Чего-то не вижу такого форматирования...
Кодом людям нужно помогать!
Re[5]: Фреймворк для тестирования сервиса.
От: Aikin Беларусь kavaleu.ru
Дата: 23.01.13 11:07
Оценка: 3 (1)
Здравствуйте, Sharov, Вы писали:

A>>А самое главное, почему бы не сгенерить клиента к этому сервису (как советует <b>.</b>
Автор: .
Дата: 22.01.13
), а далее уже использовать любой из инструментов тестирования (а уж в них прикрутить IScenario и проч. не сставит труда).

S>Так и сделал.
Ну так подключай к нему BDD (фреймворков куча).
Почему BDD? Я, ес. честно, не видел более удобного способа описывать сценарии которые друг от друга отличаются на чуть-чуть (я про переиспользование уже написанного кода).

A>>Я именно так и тестирую свои сервисы. Только я не тестировал сам WCF сервис, я напрямую создавал объект сервиса в коде (благо WCF позволяет это) и вызывл его через его интерфейс.

S>Вы не могли бы подробнее? Т.е. Вы просто локально тестировали какой-то сервисный объект, без удаленного взаимодействия?
Да, сервис мой, тест мой, задача была протестировать бизнесс сценарии, а не реализацию WCF в .net
Поэтому было принято решение вызвать сервис напрямую, а не хостить сервис и поключаться к нему клиентом.

Подробности:
Вот у нас есть Services.SomeService c интерфейсом Services.IService. Вместо того чтобы запускать реальный сервис и делать тестового клиента Tests.SomeServiceClient с интерфейсом Tests.IService и работы через Tests.IService, я напрямую создаю Services.SomeService и работаю через Services.IService
В плюсе скорость выполнения тестов и более простая инфраструктура, в минусе -- это не настоящий интеграционный тест (т.е. мой тест может пропустить баг из-за проблем в WCF).

Вроде все довольно очевидно, не рокет сайнс.

СУВ, Aikin
... << RSDN@Home 1.2.0 alpha 5 rev. 1539>>
Re[7]: Фреймворк для тестирования сервиса.
От: . Великобритания  
Дата: 23.01.13 11:58
Оценка: 6 (1)
Здравствуйте, Sharov, Вы писали:

S>Здравствуйте, ., Вы писали:


.>>Можно пример? Просто непонятно зачем тут эти интерфейсы, зачем вводить понятие "сценарий", "шаг" и т.п.?


S>Я пишу сценарий, декорирую его атрибутом, выбираю все классы по этому атрибуту, инициализирую, привожу к интерфейсу

S>сценария и выполняю.
Не понял. test framework не используешь? Я из java-мира, что там в c# плохо знаю что происходит, но вроде как есть, например, NUnit, там твоё хозяйство будет выглядить так:

[TestFixture]
public class UserTest
{
  private Client Client;

  [SetUp] public void SetUp()
  {
    Client = new Client();
    string _credentials = ScnHelper.GenerateTestUserCredentials();
    Assert.True(Client.authorize(_credentials));
  }
  
  [TearDown] public void TearDown()
  {
    Client.Destroy();
  }
  
  [Test] public void userCreation()
  {
    User user = Client.createUser("vasya", 1985);
    Assert.AreEqual(user.GetName(), "vasya");
...
  }
  [ExpectedException(typeof(UserTooYoungException))]
  [Test] public void userAnotherCreation()
  {
    User user = Client.createUser("vasenka", 2007);
...
  }
}

А вот "new Something(...).ExecuteStep()" это трешъ и угаръ...

S>PS. Прощу прощения, а как вставлять скрытый текст? Чего-то не вижу такого форматирования...

  Так?
Вот так вроде
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[8]: Фреймворк для тестирования сервиса.
От: Sharov Россия  
Дата: 23.01.13 12:19
Оценка:
Здравствуйте, ., Вы писали:

.>Здравствуйте, Sharov, Вы писали:


.>Не понял. test framework не используешь? Я из java-мира, что там в c# плохо знаю что происходит, но вроде как есть, например, NUnit, там твоё хозяйство будет выглядить так:


Я бы все-таки не стал смешивать юнит-тесты, которые в идеале должны быть
без side-effect'ов с интеграционными (боевое тестирование, жизненное).
Поэтому и написал свое решение.

.>А вот "new Something(...).ExecuteStep()" это трешъ и угаръ...


С чего бы?

  Благодарю!
!
Кодом людям нужно помогать!
Re[9]: Фреймворк для тестирования сервиса.
От: . Великобритания  
Дата: 23.01.13 13:16
Оценка:
Здравствуйте, Sharov, Вы писали:

.>>Не понял. test framework не используешь? Я из java-мира, что там в c# плохо знаю что происходит, но вроде как есть, например, NUnit, там твоё хозяйство будет выглядить так:


S>Я бы все-таки не стал смешивать юнит-тесты, которые в идеале должны быть

S>без side-effect'ов с интеграционными (боевое тестирование, жизненное).
S>Поэтому и написал свое решение.
Это заблуждение, что NUnit только для юнит-тестов. Просто набор тестов отделяется и их называют "интеграционные тесты", запуская их отдельно, т.к. они требуют внешнего окружения, типа СУБД, веб-серверов, етс. Код же выглядит точно так же. Зачем переизобретать велосипед?
BDD же нужен больше для больших проектов, чтобы сами сценарии можно было описывать естественным языком, для облегчения документирования и взаимодействия с бизнес-аналитиками и прочими непрограммистами.

.>>А вот "new Something(...).ExecuteStep()" это трешъ и угаръ...

S>С чего бы?
Ну как бы тогда накой тут интерфейс, если точный тип известен в той же строке? Только ограничивает возможности, например, типы возвращаемого значения и т.п.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[10]: Фреймворк для тестирования сервиса.
От: Sharov Россия  
Дата: 23.01.13 13:40
Оценка:
Здравствуйте, ., Вы писали:

.>Здравствуйте, Sharov, Вы писали:


.>Это заблуждение, что NUnit только для юнит-тестов. Просто набор тестов отделяется и их называют "интеграционные тесты", запуская их отдельно, т.к. они требуют внешнего окружения, типа СУБД, веб-серверов, етс. Код же выглядит точно так же. Зачем переизобретать велосипед?


Идея интересная, но все же есть свои минусы: в моем случае я вынес дополнительный настройки в UI,
я могу выбирать какие сценарии выполнять, последовательно или параллельно (т.е. создавать нагрузку),
контролирую сервис(перезапустить, приостановить и т.д.).
В случае юнит-тестов это не очень просто. Необходимо будет дублировать код: для разных настроек, по-разному сгруппированные сценарии,
последовательно или параллельно и т.д. Что-то изменить/добавить -- лезь в код, перекомпилируй. Тут же все не лету.
Велосипед не такой уж и большой.

.>BDD же нужен больше для больших проектов, чтобы сами сценарии можно было описывать естественным языком, для облегчения документирования и

.>взаимодействия с бизнес-аналитиками и прочими непрограммистами.

Угу.


.>>>А вот "new Something(...).ExecuteStep()" это трешъ и угаръ...

S>>С чего бы?
.>Ну как бы тогда накой тут интерфейс, если точный тип известен в той же строке? Только ограничивает возможности, например, типы возвращаемого значения и т.п.

Вообще говоря, там интерфейс обощенный и возвращаемый типы зависят от шага -- где-то надо bool, где надо чей-то id для
последующей обработки.

internal interface IExecuteStep<out T> : IExecute
    {
        new T ExecuteStep();
    }

    internal interface IExecute
    {
        bool ExecuteStep();

    }
Кодом людям нужно помогать!
Re[11]: Фреймворк для тестирования сервиса.
От: . Великобритания  
Дата: 23.01.13 15:34
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Идея интересная, но все же есть свои минусы: в моем случае я вынес дополнительный настройки в UI,

S>я могу выбирать какие сценарии выполнять, последовательно или параллельно (т.е. создавать нагрузку),
S>контролирую сервис(перезапустить, приостановить и т.д.).
S>В случае юнит-тестов это не очень просто. Необходимо будет дублировать код: для разных настроек, по-разному сгруппированные сценарии,
S>последовательно или параллельно и т.д. Что-то изменить/добавить -- лезь в код, перекомпилируй. Тут же все не лету.
S>Велосипед не такой уж и большой.
NUnit это фреймворк скорее для автоматических тестов. И юнит-тесты, и интеграционные тесты являются автоматическими тестами. А у тебя тут UI говоришь... как это автоматирировать-то? Может тебе не фреймворк нужен, а графическая среда разработки тестов?
Не знаю как там в ваших сишарпах, а IDE для Явы содержат UI для запуска тестов — что выполнять, параллельно ли выполнять, и с какими параметрами.

S>Вообще говоря, там интерфейс обощенный и возвращаемый типы зависят от шага -- где-то надо bool, где надо чей-то id для

S>последующей обработки.
Это ладно. А зачем этот интерфейс-то нужен? Он же нигде не используется. Если в классе "CreateUserStep" убрать ": IExecuteStep" — что изменится?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[12]: Фреймворк для тестирования сервиса.
От: Sharov Россия  
Дата: 23.01.13 15:53
Оценка:
Здравствуйте, ., Вы писали:

.>Здравствуйте, Sharov, Вы писали:


.>NUnit это фреймворк скорее для автоматических тестов. И юнит-тесты, и интеграционные тесты являются автоматическими тестами. А у тебя тут UI говоришь... как это автоматирировать-то? Может тебе не фреймворк нужен, а графическая среда разработки тестов?


Нет, нет, графическая не нужна. Нужно просто управлять сценариями, т.е. выкинуть какой-то сценарий и прогнать, или изменить последовательность
и прогнать заново, изменить тип протокола с tcp на http и снова прогнать. Как-то так.
Но вот идея использовать какой-нибудь тест-фреймворк довольно хороша, хотя не уверен, что воспользуюсь.


.>Это ладно. А зачем этот интерфейс-то нужен? Он же нигде не используется. Если в классе "CreateUserStep" убрать ": IExecuteStep" — что изменится?

Пока не очень нужен. В голове держал случай, когда, например, можно было бы загнать их все(шаги) в какой-нибудь список
и прогнать в цикле. Что-то типа уже предопределенной последовательности шагов.
Кодом людям нужно помогать!
Re[13]: Фреймворк для тестирования сервиса.
От: . Великобритания  
Дата: 23.01.13 18:49
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Здравствуйте, ., Вы писали:


.>>Здравствуйте, Sharov, Вы писали:


.>>NUnit это фреймворк скорее для автоматических тестов. И юнит-тесты, и интеграционные тесты являются автоматическими тестами. А у тебя тут UI говоришь... как это автоматирировать-то? Может тебе не фреймворк нужен, а графическая среда разработки тестов?

S>Нет, нет, графическая не нужна. Нужно просто управлять сценариями, т.е. выкинуть какой-то сценарий и прогнать, или изменить последовательность
S>и прогнать заново, изменить тип протокола с tcp на http и снова прогнать. Как-то так.
Думаю любой тестовый фреймворк это позволяет.

S>Но вот идея использовать какой-нибудь тест-фреймворк довольно хороша, хотя не уверен, что воспользуюсь.

Хм. А как же это соотносится с темой этого топика?

.>>Это ладно. А зачем этот интерфейс-то нужен? Он же нигде не используется. Если в классе "CreateUserStep" убрать ": IExecuteStep" — что изменится?

S>Пока не очень нужен. В голове держал случай, когда, например, можно было бы загнать их все(шаги) в какой-нибудь список
S>и прогнать в цикле. Что-то типа уже предопределенной последовательности шагов.
YAGNI...
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[14]: Фреймворк для тестирования сервиса.
От: Sharov Россия  
Дата: 23.01.13 19:19
Оценка:
Здравствуйте, ., Вы писали:


S>>Но вот идея использовать какой-нибудь тест-фреймворк довольно хороша, хотя не уверен, что воспользуюсь.

.>Хм. А как же это соотносится с темой этого топика?

Создание простенького своего или узнать о сущ. решениях. Я идею об использование юнит-тест фреймворков как-то сразу
отмел, т.к. имхо, идеологически неверно использовать для боевого тестирования, тем более сервиса. Да и есть ощущения, что кода
писать не меньше, да и гибкость не ахти. В собственном случае контроля больше.
Вот и спрашивал как народ обходиться. А народ, как я понял, просто пишет юнит-тесты и прогоняет либо локально, либо даже удаленно.
Кодом людям нужно помогать!
Re[15]: Фреймворк для тестирования сервиса.
От: . Великобритания  
Дата: 23.01.13 20:39
Оценка: 6 (1) +1
Здравствуйте, Sharov, Вы писали:

.>>Хм. А как же это соотносится с темой этого топика?

S>Создание простенького своего или узнать о сущ. решениях. Я идею об использование юнит-тест фреймворков как-то сразу
S>отмел, т.к. имхо, идеологически неверно использовать для боевого тестирования, тем более сервиса. Да и есть ощущения, что кода
S>писать не меньше, да и гибкость не ахти. В собственном случае контроля больше.
S>Вот и спрашивал как народ обходиться. А народ, как я понял, просто пишет юнит-тесты и прогоняет либо локально, либо даже удаленно.
NUnit это такая штука, которая позволяет автоматически запускать тучу тест-кейсов. Не понимаю что тут неидеологического. Разница юнит и инт тестов лишь в семантике. Запускалка работает точно так же.
Тест-фреймворки довольно гибкие. Не понимаю что тебе не хватает.
Кстати, они обычно предоставляют API для расширения, если и правда чего-то не хватит.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[3]: Фреймворк для тестирования сервиса.
От: LeonidV Ниоткуда http://vygovskiy.com
Дата: 28.01.13 17:31
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Здравствуйте, ., Вы писали:


S>либо не очень продвинутое (soapUI, например).

Подскажите, пожалуйста, аналоги soapUI.
http://jvmmemory.com — простой способ настройки JVM
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.