Я думаю, что ключевой момент кроется в фразе
Например, у нас есть сравнительно толстый фреймворк, который манипулирует тестируемым продуктом.
Вся проблема в том, что нужен фреймворк. Но есть случаи, когда его нет и на его написание нет времени или он нецелесообразен для текущих задач (могут быть случаи, сходу не назову). Вот в этих случаях надо как-то вертеться, как можно, и многие ранее запрещенные приемы могут вполне стать разрешенными.
Но, если автоматизация планируется заблаговременно, выделяется достаточное время, то не отводить время и усилия на создание фреймворка - это заблаговременное обречение проекта на провал.
Он (фреймворк) не всегда был толстым, и не всегда был вообще. Он результат непрерывного процесса реализации идеи о том, что при написании скриптов нужно не валить все в одну кучу, как это делает рекордер и как делают люди, начинающие писать скрипты по примерам из рекордера. А надо различать как минимум 3 отдельных слоя:
1.1. Получение элементов приложения таких как процесс и окна.
1.2. Элементарные операции над контролами.
2. Элементарные операция над самим приложением (с использованием 1.1 и 1.2).
3. Высокоуровневые операции над приложением (в идеале, с использованием только 2) - собственно тесты.
В п.1.1 имеется в виду, что разделяются сущности типа "процесс приложения", "главное окно приложения", "основной тулбар" от их реализаций вида Sys.Process('myApp'), Sys.Process('myApp').Window('MainForm','',-1), Sys.Process('myApp').Window('MainForm','',-1).Window('ToolBar', '', -1). То есть, имеются функции, которые скрывают подробности получения конкретных объектов. Например, для получения процесса вы вызываете функцию MyAppProcess, для получения главного окна GetMainForm, для получения основного тулбара GetFromMainForm('основной тулбар'), которые знают как устроены кишки приложения (с точки зрения иерархии объектов) и больше никто кроме них об этом не знает, и все изменения касающиеся этих вещей не выходят за пределы этих функций.
В п.1.2 имеется в виду, что разделяются сущности типа "кликнуть на кнопку 'Открыть' на тулбаре", "вызвать пункт 'Выход' во всплывающем меню" от их реализаций вида tbWindow.Window('TButton', 'Открыть', -1).Click, mainForm.PopupMenu.Click('Выход'). Т.е. имеются вызовы типа ClickOnTbButton(tbWindow, 'Открыть'), ClickPopupMenuItem('Выход'), которые знают как найти кнопку на тулбаре по ее имени в зависимости от класса тулбара, как найти пункт всплывающего меню. Которые проведут всевозможные проверки типа "а есть ли кнопка?" "а не задизейблена ли она?", "а есть ли такой пункт меню?", проверят успешность выполнения операции и тщательно задокументируют в лог всю информацию, необходимую для того чтобы потом понять а что же собственно делали. Здесь локализуется вся информация по работе с контролами, и тот кто вызывает эти методы не парится о деталях.
В 2 идет взаимодействие 1.1 и 1.2. Операции типа "запустить/закрыть приложение", "сохранить документ в файл", "изменить настройки на заданные" отделяются от их конкретной реализации. Берутся окна-контролы из 1.1 и проводятся над ними действия с помощью 1.2. Также выполняются всевозможные проверки (на которые забьют при написании скриптов методом "рекордера") и документируется процесс исполнения. Это представляется в виде вызовов вида StartMyCoolApp, CloseMyCoolApp, SetSettingsTo([['property1', value1], ['property2', value2]]). Здесь локализуется информация о технических деталях манипулирования приложением.
Ну в п.3 собственно с помощью п.2 (и комбинации п.1.1 и п.1.2, которые в процессе выделяются в п.2) реализуются уже тесты. Операции типа "запустить приложение, загрузить файл, проверить что содержится определенная строка, вставить что-то из буфера обмена, сохранить на диск, проверить что сохранилось то что ожидалось" реализуются с помощью кирпичиков из п.2. Эта часть составляет основной объем от всего объема кода, требует менее квалифицированного тестировщика (подойдет обычный тестер со знаниями программирования в объеме средней школы). При ее написании ему нет необходимости заморачиваться всякими окошками, тулбарами и т.п. деталями, он концентрируется именно на тестировании. Разработка тестов идет быстро (быстрее чем запись рекордером и последующая правка).
Казалось бы все это сложно и требует кучи времени. Отнюдь. Затраты времени лишь в начале автоматизации больше чем если применять "метод рекордера". Пункты с 1 по 2 изначально могут быть всего лишь обертками вокруг соответствующего функционала, предоставляемого тесткомплитом. А с ходом разработки затраты времени постоянно падают, т.к. накапливается качественный повторно используемый код, т.к. всевозможные изменения приложения затрагивают лишь небольшие части кода и не расползаются по нему бесконтрольно. Создание фреймворка идет вместе с процессом автоматизации (он постепенно сам собой выкристаллизовывается из тупых оберток, главное изначально его иметь в мыслях), и дает выигрыш буквально с самого начала из-за более понятной структуры.
Причем часть фреймворка + используемый подход становится вообще общим, не зависящим от конкретного проекта и используются для тестирования совершенно новых проектов, сразу ставя их на прочный фундамент и ускоряя выход результата.
Я не понимаю, как занимаясь автоматизацией тестирования больше 2-3 месяцев можно использовать рекордер? Это как ползающий младенец, большинство проходят через этот этап и начинают ходить, и печально смотреть на того кому это не удается. Если проще писать скрипты с помощью рекордера, то это повод остановится и хорошенько подумать.