Pull to refresh
27
0
Валерий Северин @Selmaril

Разработка ПО

Send message
У меня получилось собрать 3D принтер типа RepRap Prusa i3 за 130$ + 6000 рублей.

Первый раз гемор ещё тот, но вот если собирать второй-третий принтер для кого-то, то может выйти ещё дешевле и без тех косяков, что были в первый раз.

В кратце, на Aliexpress покупается Arduino, RAMPS, Nema 17 шаговики (5 шт.), HotEnd, Столик с подогревом, всякие ленты, подшипники и прочее. Вот список и ценники:
  • J-head Hotend for 1.75mm E3D — $11.40
  • 5 pcs Nema 17 Stepper Motor 42 — $49.30
  • 10 pcs 608ZZ — $4.60
  • 10 pcs LM8UU — $6.00
  • GT2-6mm, GT2 Belt — $5.55
  • MK8 Driver gear — $3.26
  • High Temperature Insulation Tape BGA 5mm/10mm/15mm x 33m — $7.50
  • PCB Heatbed MK2B — $7.89
  • Mega 2560 R3 + RAMPS 1.4 Controller + 5pcs A4988 Stepper Driver Module + 2004 controller for 3D Printer kit — $28.49
  • 5 pcs Endstop Optical Optics limit switch for RAMPS 1.4 — $4.74


Корпус можно вырезать в Москве за 4500 р. в какой-нибудь конторе (например тут: Сделано Лазером). Чертежи есть в интернете, например Graber. Далее закупаем сотни болтиков, всяческие шпильки, мелочовку, направляющие, и… Оно будет работать! Всего за ~14 000 рублей (зависит от курса).
Мотоциклетные номера в поиск добавьте:
image
Там чем дальше, тем меньше воды. Первая треть по сути просто вправляет мозг и показывает что есть проблема. Показывает на практически бытовых, разжеванных примерах. Потому и долго.
Да, все верно. Объекты JS, компоненты в JS и прочее. Парадигма такая — извлекать информацию с помощью JS команд через Selenium, делать действие с помощью IWebElement (клики, вводы и прочее). Получилось достаточно просто собрать модель тестируемой системы в тесте, и при этом имитировать пользовательские действия с помощью Selenium.

Меня правда огорчают проблемы при обновлении Web драйверов Selenium, но всегда можно найти костыли для решения.
Карьерный экскаватор завидует скорости вашего копания!

По поводу параллелизма, да, я имел ввиду системы непрерывной интеграции. У нас был TeamCity.

Если интересно ради самообразования, то у нас получилось что-то вроде этого: habrahabr.ru/post/181660/

Только последний месяц-два была сильная подвижка, код теперь выглядит так:

[Test]
    public void DocumentOperationGridOperationTest()
    {
        var grid = Env.Navigation.OpenList<BaseInDocumentImpl>();
        
        grid.Toolbar.Click(typeof(CreateDocument));

        var docForm = Env.TabPanel.GetForm<BaseInDocumentImpl>();
        docForm.finishOperation();
        docForm.Close();

        var grid = Env.Navigation.OpenList<BaseInDocument>();

        grid.Data.First().Select();
        grid.Toolbar.Click(typeof(Operations), typeof(CreateDocument));

        var docForm = grid.OpenForm();

        var fieldValue = docForm.ForMember(la => la.SomeNewField).GetField<TextField>();
        Assert.False(string.IsNullOrEmpty(fieldValue.GetValue()), "Не заполнилось поле которое должно быть заполнено в классе операции, то есть не вызвался класс операций для документа");
        grid.DeleteFirstRow();
        docForm.Close();
    }


Соответственно в тесте мы оперируем такими терминами как Сущности (BaseInDocumentImpl, BaseInDocument), Действиями (это то, что воплощается в кнопки, прикладной код — Operations, CreateDocument), и собственно указывать лямбда выражениями над чем мы хотим работать в сущности (ForMember(la => la.SomeNewField).GetField(), SomeNewField — это поле типа сущности).

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

Основной смысл тестов — убедиться что на крайней линии сложная цепочка действий выполняется без каких-либо отклонений. Фактически что можно провести тот или иной бизнес-процесс. Например провести определенный документ и получить нужные данные.

Конечно такие тесты не способны детализировать интерфейс, если есть такая потребность, то можно делать вставки голым Selenium или JavaScript. Но как показала практика — стабильные тесты таким образом простые разработчики написать не могут. Нужно понимать работу сложного интерфейса, крайне динамичного. Это сложно.

В общем как-то так оно вышло.

А вы исключительно тестированием занимаетесь? Просто то, что вы описали — это работа одного-двух человек в течении месяца, полутора. Интересно как в вашей организации процесс тестирования поставлен.

У нас API разрабатывал я, при этом я же занимался частью View (серверная и клиентская). Ещё 2 человека занимались бэкендом. Это ядро. Один человек ведет TeamCity. Есть ещё 10 прикладных разработчиков, которые пишут бизнес-логику. На разработку первой очереди API для тестов ушел где-то месяц. С тех пор он регулярно дорабатывался, в последний раз была введена более жесткая типизация (на это потребовалось дня 3). Сам Selenium живет уже год, написано 70+ тестов, они проходят где-то час в 2 потока. Интересное наблюдение — на поддержку тестов уходит больше времени, чем на написание API, развертывание и написание самих тестов. С одной стороны это говорит о не слишком высоком качестве API, с другой стороны это можно объяснить высокой динамикой интерфейса (написанного на ExtJS). Но если подумать, то без API покрыть Selenium тесты такую систему вообще было бы нереально, если даже API тяжело стабилизировать.

В последнее время 1 из 3 падений теста говорили о реальной проблеме в системе, ещё 1 говорило о несоответствии логики теста логике (возможно изменившейся) системы, а последнее случалось из-за проблем с самим API теста. Как-то так.
Прочитал вашу статью, укрепился в своем мнении о подходах к тестированию Selenium:
— У вас многостраничный сайт с простым взаимодействием? Не парьтесь, записывайте тесты средствами Selenium прямо в браузере. Проще перетцкать 5 ссылок и проверить что в DIV-е c определенным CSS классом есть нужный текст, чем цеплять PageObject и писать враппер. Даже если тест перестанет быть актуальным, все равно его проще перезаписать.

— У вас многостраничный сайт со сложным взаимодействием, кучей ajax? Делайте PageObject, используйте готовые каркасы, делайте обертки доступа. В общем весь тот смак, что у вас в статье. Только не думаю что это осилит обычный тестировщик. Тут надо запрягать программиста, разбирающегося в вашем View. Некоторые кодовые концепции, мягко говоря, стоят программиста от 100 000 в месяц. Высококлассного разработчика иногда жалко кидать на тестирование, но без столь серьезного подхода имхо автоматизировать тестирование таких штук не выйдет.

— У вас одностраничное сложное интернет приложение (RIA), с кучей AJAX и JavaScript. Да у вас HTML в исходниках меньше, чем JavaScript. Тут PageObject уже не пойдет, т.к. это автоматически GodObject будет. Надо писать сложную обертку для тестов, отталкиваясь от модели вашего приложения (а не того, что там можно на странице сделать или увидеть). Т.е. не уметь тыкать по DOM элементам, а уметь оперировать абстракциями системы (кнопки, операции, таблицы, формы, рабочие столы, деревья навигации и т.п.). Это тоже целое море, но архитектурно с PageObject общего ничего не имеет (у меня такой вариант получился).

Боже мой, MethodInterceptor в интеграционном тестировании… Куда катится этот мир, где те милые тестерши, которые с круглыми глазами приходят к тебе и говорят «Ой, я кажется багу нашла! Но не уверена :\ Ты не мог бы посмотреть». А ты такой подходишь, смотришь, жмакаешь F12, пишешь пару волшебных строчек, и оно снова работает. И на тебя смотрят то ли как на колдуна темного, то ли как на героя… Ушли времена, совсем ушли…

Кстати, а вы как-то параллелите запуск тестов на билд сервере? С этим обычно сложности бывают в плане организации технической части.
Вы исходите из предположения, что клиент на ExtJS у нас толстый, но это не так. Он очень тоненький и не является источником, либо хранилищем данных (за исключением редактируемой в данный момент формы). Клиент — это лишь отображение данных.

А ещё мы используем Ext.NET, так что необходимости собирать ExtJS у нас нет.

Теперь по вопросам:
1. Текущий проект был переписан на ExtJS 3 с нуля. На ExtJS 4 происходит миграция, с болью конечно, но за пару месяцев управлюсь. У нас очень много изменений в компонентах.
2. Нет необходимости. Ресурсами управляет Ext.NET, он сам собирает скрипты.
3. Редактируемые GridPanel у нас есть, но REST store мы не использовали. Самостоятельно обходим набор данных хранилища, формируем в один запрос все изменения и шлем на сервер. Это обусловлено сложной структурой данных, отображаемых в редактируемом списке, и их не полной транзитивностью.
4. Такой необходимости нет, клиент оооочень тонкий. Все что он загружает при старте — дерево навигации, да пяток компонентов-виджетов (асинхронно по событиям).
5. Одновременно с программой работают десятки людей. Проблемы с синхронизацией не возникают. В принципе сервер управляет этим, отправляя команды обновления наборов данных в некоторых случаях. Конкретная запись данных версионна и это проверяется на сервере. Так что с синхронизацией проблемы решать не пришлось.
Если в кратце, то наберите в отладчике на указанной вами странице это:

Ext.ComponentManager.each(function (id, item){console.log(id, item.getXTypes(), item.initialConfig)})

В консоль выведется весь список компонентов. Из них уже можно вытянуть Id DOM узла, или ссылку на него (Ext.getCmp('id').body.dom — например). Далее этот Id или ссылку (да, да, именно ссылку на DOM) можно передать в Selenium.

Тут все более менее понятно. Вопрос как найти нужный компонент.

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

Получается мы можем восстановить иерархию компонентов с одной стороны, и с другой стороны выцепить нужный компонент. А самому Selenium не нужен именно Id, ему нужна ссылка на DOM узел. Да но можно передавать и Id, дело вкуса.

Кстати, ExtJS так устроен, что идентификатор компонента соответствует идентификатору корневого DOM узла из верстки этого компонента. Т.е. можно по Id найти контейнер и по нему кликнуть, а по контейнеру можно найти компонент, и выцепить информацию о его конфигурации, где могут быть определяющие назначение этого компонента зарубки.

+ Можно в некоторых случаях и DOM шаблон компонента переопределить. Но это трудозатратно и нудно, я так делать перестал, от идеи отказался.
Я бы поучаствовал в идее и каркасе OpenSource ядра тестирования, но не уверен что смогу найти время чтоб поднять такой проект самому. Все же текущее ядро достаточно специализированно, и оно тем лучше, чем лучше отражает бизнесс объекты тестируемой системы. Цель универсальности не ложится в постановку на эту работу увы :\ Но если готовы поучаствовать, то можно замутить что-то :) Я бы объяснил в деталях как оно работает. В общем велкам, в ЛС.
Да, решил! Правда потребовался сдвиг мышления.

Все же мы тестируем высокоуровневый функционал, то, как компоненты ведут себя вместе, как они реализуют системный функционл. А ещё тестируем сложные цепочки вызовов, которые не из интерфейса сложно проверить. Ну и гарантируем то, что версия продукта не будет иметь очевидных проблем с точки зрения конечного пользователя (на покрытых участках, естественно).

В общем мы не проверяем сами компоненты ExtJS. Ну, проверяем конечно, но это побочный эффект. Нам важно чтоб пользователь мог выполнить задачу, а то что компоненты работают верно — эффект побочный.

Так вот, тесты во время выполнения делают инъекции в тестируемый код *увернулся от помидорки*. Правда очень ограниченные, и эти инъекции не должны изменить логику тестируемого стенда.

В частности для AJAX, перед вызовом добавляется подписчик, который регистрирует этот вызов в глобальной коллекции. А по выполнению (или на отказ) вешается другой подписчик, который во первых изменяет состояние глобальной коллекции, а во вторых зачищает за собой весь мусор.

Таким образом мы пуляем событие на выполнение AJAX (жмем кнопку, обновляем список и т.п.), и после этого начинаем долбить Selenium-ом браузер на предмет завершенности запроса в данной глобальной коллекции. Выходит что нам не важно что должно будет прийти на AJAX запрос (а там такой адЪ приходит порой), нам важно чтоб в принципе запрос завершился. И нам не надо ждать больше положенного. Соответственно пока Selenium не убедился что запрос закончен, он не передает управление прикладному коду теста. Это упрощает тест. Разработчику теста даже не надо думать что его кнопочка что-то там куда-то услала, он просто проверяет что после того, как нажал кнопочку появилось окошко с надписью «Учапу»! И это прекрасно ^_^ А ещё мы вместо тестера перехватываем все технические ошибки (запрос не прошел, вернулся не тот формат, требуется аутендификация и т.п.).

Вот как-то так.
Простил по разочку все посты, и ещё разок в карму простил. Спасибо за уроки, очень кстати!
Выглядит все очень чистенько и удобно. Не уверен что так можно сделать без детального проектирования взаимодействия, но в реалиях разработки корпоративного продукта это зачастую не считается важной частью, ей не уделяют достаточно времени и вообще, нет дизайнеров… (кстати, откуда вы взяли дизайнера, очень приятно все выглядит… он готов к новым заказам? ^.^) Так что впечатляет очень очень!

Мы подобные проблемы решили подобным образом, правда у нас одностраничное приложение (без фреймов). Не очень понял про фрейм со скриптами (в смысле понял, но без знания как у вас организована страница это понимание не полное). А так кеш структуры страницы/формы, отделение структуры от данных и метаданных, соответственно врознь это формировать… непростая наверно была задачка, вы круты! С кешем информации для построения (настроек например) можно дальше пойти. Если вы уж вынесли их в готовые объекты, то не так важно откуда заполняются эти объекта, а значит можно часть настроек было бы вынести в более быстрые хранилища, например объектуню БД. Фантазия на эту тему безудержна, уверен что вы уже что-то такое делаете, удачи вам в совершенствовании :) Вообще очень интересно подглядывать за вашим проектом!

В том году я писал статью — сравнительный анализ интерфейсов разных Web ERP платформ, очень хотел посмотреть Акуматику, но вашей демки в публичном доступе не нашел, только видео и скрины. Расстроился :\ Даже забыл выпилить из заглавной картинки упоминание о вас, хотя безумно хотелось потыкать, на скринах все выглядело очень круто (да, да, даже за страшненьким дизйном чувствуется вся мощь бэкенда).
Понимаю и уважаю вашу боль…

У меня C#/NUnit/TeamCity

В процессе работы с Selenium я пришел к мысли, что не важно как получать доступ к WebElement-у, важно что и как с ним дальше делать. Исходя из этого, в своих тестах, я стараюсь делать сложные выборки с помощью JS кода. Выходит гораздо более стабильно и точно (хотя этому способствует ExtJS, на котором написан front-end). Даже если я получаю элемент, недоступный, скажем, для нажатия, то в момент нажатия правда вскрывается и тест законно падает. Зато бубнов нет с селекторами, ожиданиями и прочей болью.

Если посмотреть лог файл после тестов, то видно все низкоуровневые команды от Selenium к браузеру. Там видно как он делает это ожидание, так что ничего плохого в собственных велосипедах по этой части нету.

Все что пулается от Selenium к браузеру может потеряться. По этому не грех повторять действия, а на JS команды вешать хитрые маркеры, чтоб понять дошли ли они, интерпретировались ли.

Снимать скриншоты — великое добро.

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

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

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

«Error communicating with the remote browser» — встречал и под ChromeDriver :\ Честно сказать есть некоторый страх при обновлении драйвера или тестового браузера, что очень плохо.

Самая большая проблема возникла с разработчиками тестов. Я им предоставил API, они пишут тесты, тесты выполняются через NUnit. Проблема в том, что они пишут их как Unit тесты, а не как какие-то большие интеграционные тесты. Получается полная хрень, типа тест на 30 секунд, который проверяет нажимается ли кнопочка в выпадающем меню. При этом эта функция используется во всех тестах, но есть специальный тест, который типа это проверяет. В общем сдвинуть парадигму восприятия нереально трудно. С таким подходом тестовый билд (TeamCity) пухнет по времени до часу, а по факту проверяет элементарные, скучные вещи, причем стопицотраз дублировано. Беда.

Очень интересно как вы разворачивали Selenium Grid. У нас тесты есть, но мы их на гриде не параллели, скоро предстоит, может поделитесь опытом/ссылками? :)
Коль настаиваете: books.ru :) Просто негоже рекламу писать первым комментом… хотя на таких условиях, какая к черту реклама!
Не так давно прочел книгу: «Алан Купер об интерфейсе. Основы проектирования взаимодействия» (ISBN 978-5-93286-132-5, 978- 0-470-08411-3;). Примерно 700 страниц о том, о чем вы тут написали. Очень рекомендую, книжка поможет разобраться в том, что же такое интерфейс, что такое взаимодействие, что такое ментальная модель, и чего собственно хочет пользователь. Понимая это, и ещё кучу вещей, вы легко определите границу компетенции дизайнера, заказчика и проектировщика (т.е. свою), и сможете концентрироваться в ТЗ на тех вещах, которые действительно важны. Книгу можно купить за рубль на буксах, была ссылка на хабре на акцию, она ещё действует.
DSL в смысле языка для тестов, или в смысле языка для прикладной (бизнес) логики? А в целом понял, спасибо!

В идеале бы свести написания хотя бы скелета теста к тому, чтоб протыкать аналитику по его же процессу в интерфейса. Тогда, наверно, этим реально начнут пользоваться. Своего рода запись макросов.
Есть роли менеджер и разработчик.
Менеджер смотрит факт падения теста (красный кружочек в TeamCity), блокирует выпуск версии, ставит задачу разработчику разобраться с тестом.

Разработчик иногда заглядывает в тесты, иногда смотрит этот лог, пытается повторить проблему по нему, зафиксировать, решить.

Как-то так. Там кстати есть стектрейс:
NUnit.Framework.AssertionException: Форма не содержит информацию о зависимостях Expected: True But was: False at NUnit.Framework.Assert.That(Object actual, IResolveConstraint expression, String message, Object[] args) at Selenium.GridActionTest.OnlyOpenActionFoms() in d:\Team\BuildAgent\SedDatServAgent2\work\195b9fcc838c17ee\Source\Selenium\GridActionTest.cs:line 105

Упал на Assert. Если бы была серверная ошибка, то показался бы её трейс.

Все это генерируется автоматически, по шагам теста. Т.е. вручную пишутся только ассерты, можно добавлять информацию по шагам. Когда случилось падение — снимаются скриншоты. Если пришло с сервера что-то, что может быть ошибкой, то это так же приписывается к логу, ну и т.п.

Т.к. этим ограниченно пользуются, то мне непонятно в какую сторону развивать. Вышло во все по немногу. Конечного потребителя, плотно работающего с этими тестами нет :\ Собственно отсюда мой местами нелепый интерес, посмотреть как оно у белых людей :)
А не думали о настоящей паралельности? Ведь большинство тестов UI не конфликтуют друг с другом, а серверную часть нагружают крайне мало. Выходит что весь пакет тестов можно выполнить за время самого длинного теста.

Я вообще разработчик View. Мои проблемы тесты UI решают — мы не выпускаем продукт, в котором не запускается интерфейс (а раньше были прецеденты). А какие классы проблем решаете вы? По статье понятно что у вас большой стек кейсов по прикладным и бизнес задачам, но например какие они? Что конкретно решают, кто решил что это важные аспекты, от кого исходила инициатива написать тест кейс, или зафиксировать процесс (кроме ручных тестеровщиков, как я понял из статьи)?
А вот пример отчета о падении: www.peeep.us/0586b385

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity