Ответ 1
После нескольких экспериментов я разработал то, что представляется комбинацией настроек, которые позволяют моим Coded UI Tests надежно запускаться на полной скорости - быстрее, чем я мог бы взаимодействовать с сайтом вручную.
Примечание. Соответствующую "документацию" (если вы называете "документацию" в блоге) можно найти здесь:
Трюк требует нескольких модификаций настроек воспроизведения по умолчанию:
-
Настройка
WaitForReadyLevel = WaitForReadyLevel.Disabled
позволяет запустить тест на полной скорости. Но он также отключает магию (медленную!), Которая ждет, пока не будет безопасно взаимодействовать с элементами управления на странице. -
Установка
MaximumRetryCount
и прикрепление обработчика ошибок обрабатывает большинство ошибок, возникающих в результате отключения магии "ждать готовности". Поскольку я запекал 1 секундуSleep
в логике повтора, это значение фактически представляет собой количество секунд, которые я готов дождаться загрузки страницы и стать отзывчивым. -
По-видимому, неспособность найти проверяемый элемент управления не является одной из ошибок, которые обрабатывает механизм обработчика ошибок/повторов. Если для загрузки новой страницы требуется больше нескольких секунд, и тест ищет элемент управления, который не существует до тех пор, пока новая страница не загрузится, тест не сможет найти элемент управления, и тест завершится с ошибкой. Настройка
ShouldSearchFailFast = false
решает эту проблему, предоставляя вам полный тайм-аут для загрузки вашей страницы. -
Настройка
DelayBetweenActions = 500
, похоже, устраняет проблему, которую я иногда вижу, когда пользовательский интерфейс пропускает нажатие кнопки, которое происходит сразу после загрузки страницы. Кажется, что тестовое оборудование думает, что нажата кнопка, но веб-страница не отвечает на него. -
В "документации" говорится, что тайм-аут поиска по умолчанию составляет 3 минуты, но на самом деле это нечто большее 10 минут, поэтому я явно устанавливаю
SearchTimeout
на 1 секунду (1000 мс).
Чтобы сохранить весь код в одном месте, я создал класс, содержащий код, используемый всеми тестами. MyCodedUITests.StartTest()
вызывается методом [TestInitialize]
в каждом из моих тестовых классов.
Этот код действительно должен выполняться только один раз для всех тестов (а не один раз для каждого теста), но я не мог понять, как заставить вызовы Playback.PlaybackSettings
работать в [AssemblyInitialization]
или [ClassInitialization]
подпрограммы.
/// <summary> A class containing Coded UI Tests. </summary>
[CodedUITest]
public class UI_Tests
{
/// <summary> Common initialization for all of the tests in this class. </summary>
[TestInitialize]
public void TestInit()
{
// Call a common routine to set up the test
MyCodedUITests.StartTest();
}
/// <summary> Some test. </summary>
[TestMethod]
public void SomeTest()
{
this.UIMap.Assert_HomePageElements();
this.UIMap.Recorded_DoSomething();
this.UIMap.Assert_FinalPageElements();
}
}
/// <summary> Coded UI Test support routines. </summary>
class MyCodedUITests
{
/// <summary> Test startup. </summary>
public static void StartTest()
{
// Configure the playback engine
Playback.PlaybackSettings.WaitForReadyLevel = WaitForReadyLevel.Disabled;
Playback.PlaybackSettings.MaximumRetryCount = 10;
Playback.PlaybackSettings.ShouldSearchFailFast = false;
Playback.PlaybackSettings.DelayBetweenActions = 500;
Playback.PlaybackSettings.SearchTimeout = 1000;
// Add the error handler
Playback.PlaybackError -= Playback_PlaybackError; // Remove the handler if it already added
Playback.PlaybackError += Playback_PlaybackError; // Ta dah...
}
/// <summary> PlaybackError event handler. </summary>
private static void Playback_PlaybackError(object sender, PlaybackErrorEventArgs e)
{
// Wait a second
System.Threading.Thread.Sleep(1000);
// Retry the failed test operation
e.Result = PlaybackErrorOptions.Retry;
}
}