...

суббота, 16 мая 2020 г.

Почему Axure могла нагнуть Sketch и Figma, но не нагнула

Эта статья не является историческим справочником с датами, вехами развития и секретными инсайтами, а лишь мой взгляд в историю развития продуктов и размышление о том почему Axure, имея всё то, за что мы так любим Скетч и Фигму, ещё задолго до появления оных, теперь ютится на задворках, но занимает особое место в сердцах хардкорных проектировщиков.

А ещё: Это не сравнение кто круче и не попытка засрать ваш любимый инструмент работы, каким бы он ни был.

Моё знакомство с Акшурой (здесь и далее я буду писать это название именно так) началось, нет, не с первых версий, как это часто бывает в подобных статьях, а с версии 6 или 7. Но те кто знает с какой периодичностью Акшура выпускает новые мажорные версии, понимает, что это было довольно давно.

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

Давайте пробежимся по функциям, которые уже были в версии 7 и, которые широкое распространение получили только с приходом Скетча и Фигмы.

  • Компоненты. Да-да, те самые Символы (у Скетч) и Компоненты (у Фигмы), уже давно были и есть в Акшур. Только называются они Мастера. Принцип и логика работы мастеров абсолютна такая же, как у современных аналогов.

  • Стили. Предзаданные стили, которые можно быстро применять к любому тексту или объекту.
  • Библиотеки. Есть и были особые файлы в которых дизайнеры собирали свои компоненты и эти файлы можно было легко пристегнуть к вашему проекту и использовать не стандартные календарики и кнопочки, а специально подготовленные. Есть даже, библиотеки повторяющие стиль Бутстрапа.
  • Кликабельные прототипы. То что в Скетче появилось не так давно, а в Фигме чуть раньше с самого начала было в Акшуре. Это, по сути, была та самая киллер-фича Акшуры, которая делала её не альтернативой Фотошопу для задротов, а самостоятельным продуктом с довольно революционным подходом.
  • Выгрузка в облако. Не ручаюсь именно за версию 7 (тогда у меня была не совсем платная версия и юзать все фишки я не мог), но у 8-ки уже точно было. Не в пример лучше и стабильней того, что сейчас выкатывает Скетч.
  • Шаринг макета и комментирование. Примерно такое же, как сейчас в Фигме, только несколькими годами ранее.

  • Версионирование. Скетч для этого использует сторонний и платный Abstract. В Фигме это и не требуется судя по всему.


Что есть в Акшуре и нет в Фигме / Скетче


  • Адаптивность макетов. В Акшуре можно задать точки разрыва при которых макет будет перестраиваться у юзера на устройстве. В Фигма есть только несколько плагинов, которые просто будут эмитировать адаптивность в процессе дизайна, а не у юзера.
  • Вставка кода. Акшура сразу имела визуальный интерфейс программирования прототипа, который позволяет запрограммировать любой кусок прототипа и менять его состояния в зависимости от действий пользователя. А уж если вы знаете JavaScript, то вы можете сотворить просто что угодно в прототипе. Можете даже собрать работающий сайт. Фигма только сейчас робкими шагами идёт к интеграции кода в свой интерфейс. Естественно, в своём понимании как это должно работать и уже не JavaScript, а React, но идея встретить визуальный редактор и код далеко не нова.
  • Инструменты создания схем. Полезно для любителей создать CJM или просто структуру страниц/экранов интерфейса и логику разных сценариев. Сейчас чаще всего для этого принято использовать, например Miro или божественный Overflow, но в Акшуе это было из покон веков без необходимости прыгать в другие инструменты.

Когда я перешёл от дизайна исключительно к проектированию (сейчас уже не так), дизайнеры, которые уже начинали щупать Скетч, никак не могли понять зачем мне этот комбайн и продолжали убеждать, что Скетч лучше. Но чётко объяснить чем конкретно он лучше не мог никто. По функциям Скетч проигрывал под чистую. Преимущество Скетча было на уровне ощущений. Он был действительно, более дружелюбен и нов. В этом, как мне кажется, и кроется проблема Акшуры — она кажется сложной. Слишком много всего она умеет. Многое из этого не нужно (например, генерация документации на основе структуры прототипа) даже тем кто в ней работает каждый день. Если бы я проводил А/Б тест на привлекательность интерфейса Акшуры и Скетча результат был бы 0 против 100 не в пользу Акшуры. Но на самом деле, сравнивать Скетч и Акшуру бессмысленно. Один инструмент про создание красивого интерфейса, а другой про динамический прототип.

Самое смешное, что даже сам процесс создания и редактирования шейпов в Акшуре гораздо ближе к современным принципам «рисования» в Скетч / Фигма чем в Фотошопе тех лет. Т. е. по факту в Акшуре можно нарисовать финальный дизайн ничем не хуже чем в Фигма. Единственная проблема будет с тенями (в Акшур они не очень) и эффектами наложения слоёв (которых в Акшуре просто нет), но честно говоря наложением слоёв, лично я, и не пользовался никогда.

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

На мой взгляд Акшур в какой-то момент пережила экзистенциальный кризис, отголоски которого испытывает до сих пор. С одной стороны стремясь быть похожей на героев нового времени, с другой придерживаться своих концепций и оставаться комбайном для всего и сразу. И, кажется, разработчики выбрали первый путь и стараются держать руку на пульсе, понимая, что мир изменился. Об этом говорит хотя бы то что Акшура теперь поддерживает приём файлов и Скетча, и Фигмы и даже XD (и ни один из них не поддерживает файлы Акшуры). Правда, я не знаю никого, кто будучи в здравом уме захотел бы перейти из Фигмы в Акшур.

Этот пост для меня, как некая дань уважения к Акшуре и ностальгия по работе в ней. А также взгляд в будущее с робкой надеждой на реннесанс Акшур в массовом дизайнерском сознании. Ведь она сейчас стремительно меняется и, по сути, уже не хуже Скетча и точно лучше (оценочное суждение) XD. В новой версии появился CSS код для разрабов и даже настройка анимации для дизайнеров. Да, что я вам рассказываю. Просто проверьте сами.

Let's block ads! (Why?)

[Перевод] Лучшие практики Kubernetes. Организация Kubernetes с пространством имен

Лучшие практики Kubernetes. Создание небольших контейнеров

По мере того как вы начинаете создавать все больше и больше сервисов Kubernetes, простые по началу задачи начинают усложняться. Например, команды разработчиков не могут создавать службы или развертывания под одним и тем же именем. Если у вас тысячи подов, их простое перечисление займет кучу времени, не говоря о том, чтобы обеспечить им нормальное управление. И это только верхушка айсберга.

Давайте рассмотрим, как пространство имен namespace облегчает управление ресурсами Kubernetes. Итак, что же такое пространство имен? Namespace можно рассматривать как виртуальный кластер внутри вашего кластера Kubernetes. Вы можете иметь несколько изолированных друг от друга пространств имен внутри одного кластера Kubernetes. Они реально могут помочь вам и вашим командам с организацией, безопасностью и даже производительностью системы.

В большинстве дистрибутивов Kubernetes кластер «выходит из коробки» с пространством имен, имеющим название «default». На самом деле существует три пространства имен, с которыми Kubernetes имеет дело: default, kube-system и kube-public. В настоящее время Kube- public используется не так уж часто.

Не трогать пространство имен kube – хорошая идея, особенно в такой управляемой системе, как Google Kubernetes Engine. Она использует пространство имен «default» как место, в котором создаются ваши сервисы и приложения. В нем нет абсолютно ничего особенного, за исключением того, что Kubernetes «из коробки» настроен на его использование, и вы не можете его удалить. Это отлично подходит для начала работы и систем с небольшой производительностью, но я бы не рекомендовал использовать default namespace в больших prod-системах. В последнем случае одна команда разработчиков может легко переписать чужой код и нарушить работу другой команды, даже не осознавая этого.

Поэтому следует создать несколько пространств имен и использовать их для сегментации ваших услуг в управляемые звенья. Пространство имен можно создать с помощью одной команды. Если вы хотите создать пространство имен с именем test, то используйте команду $ kubectl create namespace test или просто создайте YAML-файл и используйте его, как любой другой ресурс Kubernetes.

Просмотреть все пространства имен можно с помощью команды $ kubectl get namespace.

После ее выполнения вы увидите три встроенных пространства имен и новое пространство имен под названием «test». Давайте рассмотрим простой YAML-файл, предназначенный для создания pod. Можно заметить, что в нем нет никакого упоминания о пространстве имен.

Если примените kubectl для запуска этого файла, он создаст модуль mypod в текущем активном пространстве имен. Это будет пространство имен по умолчанию, пока вы его не измените. Существует 2 способа сообщить Kubernetes, в каком пространстве имен вы хотите создать свой ресурс. Первый способ — это использование флага пространства имен при создании ресурса.

Второй способ заключается в указании пространства имен в декларации YAML.

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

Это происходит потому, что все команды выполняются вне текущего активного пространства имен. Чтобы найти свой pod, вам нужно использовать флаг пространства имен, однако это быстро надоедает, особенно если вы работаете разработчиком в группе, которая использует свое собственное пространство имен и не хочет и использовать такой флаг для каждой отдельной команды. Давайте посмотрим, как это можно исправить.

Из коробки ваше активное пространство имен носит название default. Если вы не уточните пространство имен в YAML ресурса, то все команды Kubernetes будут использовать это активное default namespace. К сожалению, попытка управлять активным пространством имен с помощью kubectl может окончиться неудачей. Однако существует очень хороший инструмент под названием Kubens, который намного упрощает этот процесс. Когда вы запускаете команду kubens, то видите все пространства имен с подсвеченным активным пространством имен.

Для переключения активного пространства имен на пространство имен test вы просто запускаете команду $ kubens test. Если после этого снова ввести команду $ kubens, можно увидеть, что теперь выделено новое активное пространство имен – test.

Это означает, что вам не нужен флаг пространства имен, чтобы увидеть pod в пространстве имен test.

Таким образом пространства имен скрыты друг от друга, но не изолированы друг от друга. Сервис из одного namespace может довольно легко общаться с сервисом в другом пространстве имен, что часто бывает очень полезно. Возможность коммуникации между разными пространствами имен означает, что сервис ваших разработчиков может взаимодействовать с сервисом другой dev-команды в другом пространстве имен.

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

К счастью, это легко обойти, используя развернутую форму DNS-адреса. Сервисы в Kubernetes выставляют свои конечные точки, используя общий шаблон DNS. Это выглядит примерно так:

Как правило, вам просто нужно имя сервиса, и DNS автоматически определит полный адрес.

Однако если вам нужно получить доступ к сервису в другом пространстве имен, просто используйте имя службы плюс имя пространства имен:

Например, если вы хотите подключиться к базе данных сервиса в тестовом пространстве имен, вы можете использовать базу адресов database.test

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

Если вы действительно хотите изолировать и ограничить доступ к пространству имен, Kubernetes позволяет сделать это с помощью сетевых политик Kubernetes Network Policies. Об этом я расскажу в следующей серии.

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

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

Представьте, что вы являетесь частью небольшой команды, которая работает над разработкой 5-10 микросервисов и вы легко можете собрать всех разработчиков в одной комнате. В данной ситуации имеет смысл запускать все prod-сервисы в пространстве имен default. Конечно, для большего простора действий вы можете использовать 2 пространства имен — отдельно для prod и dev. И вероятнее всего, вы тестируете свою разработку на локальном компьютере с помощью чего-то наподобие Minikube.

Предположим, что условия поменялись и теперь у вас имеется быстро растущая команда, которая одновременно работает над более чем 10 микросервисами. Наступает момент, когда необходимо использовать несколько кластеров или пространств имен, отдельно для prod и dev. Можно разбить команду на несколько подгрупп так, чтобы у каждой из них были свои собственные микросервисы и каждая из этих команд могла бы выбрать свое собственное пространство имен для облегчения процесса управления разработкой и выпуском ПО.

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

В крупных компаниях разработчики вообще не знают, кто конкретно над чем работает. Команды общаются с помощью сервисных контрактов или используют технологию Service mesh, которая добавляет над сетью уровень абстракции, типа инструмента конфигурации Istio. Попытка запустить весь стек локально просто невозможна.Я настоятельно рекомендую использовать в Kubernetes такую платформу непрерывной доставки (CD), как Spinnaker. Итак, наступает момент, когда каждой команде определенно нужно собственное пространство имен. Каждая команда даже может выбрать несколько пространств имен для среды dev и среды prod.

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

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

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

Продолжение будет совсем скоро…


Немного рекламы :)


Спасибо, что остаётесь с нами. Вам нравятся наши статьи? Хотите видеть больше интересных материалов? Поддержите нас, оформив заказ или порекомендовав знакомым, облачные VPS для разработчиков от $4.99, уникальный аналог entry-level серверов, который был придуман нами для Вас:Вся правда о VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps от $19 или как правильно делить сервер? (доступны варианты с RAID1 и RAID10, до 24 ядер и до 40GB DDR4).

Dell R730xd в 2 раза дешевле в дата-центре Equinix Tier IV в Амстердаме? Только у нас 2 х Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 ТВ от $199 в Нидерландах! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — от $99! Читайте о том Как построить инфраструктуру корп. класса c применением серверов Dell R730xd Е5-2650 v4 стоимостью 9000 евро за копейки?

Let's block ads! (Why?)

[Из песочницы] Из истории «нестандартного» радиовещания со спутника

Возможно многие не знают, (или успели забыть) но в конце 90х, начале 2000х годов, во времена перехода с аналогового на цифровое спутниковое ТВ вещание, были популярны приёмники от Nokia серии «MediaMaster».


(фото с сайта archiwum.allegro.pl)
Выпускались модели 9100/9500/9600 (отличия в комплектации RF модулятором, модемом, и т.п.). И их «заказной» вариант под немецкого провайдера DF-1 под названием DBox (1)).


(фото с сайта archiwum.allegro.pl)

По тем временам, мало того что железо было качественным по сборке и комплектующим, но оно было ещё и довольно «вкусным» и по возможностям (например наличие интерфейса SCSI).


(фото с сайта archiwum.allegro.pl)

Но… в силу некоторых причин и только зарождавшегося «маркетинга», функционал с родным FW был сильно ограничен.

Взрывной рост интереса к этим аппаратам (да и учитывая что других особо не было) произошёл после выхода альтернативных прошивок от Uli Hermann (Dr. Owerflow).

Первые, относительно публичные версии несли название DVB98, но относительно скоро переименовались в DVB2000.

Основным «локомотивом» для перепрошивки аппаратов было конечно направление, которое сейчас не принято «громко обсуждать».

Но! было и ещё одно, вполне легальное и официально просуществовавшее — прослушивание и запись (!) файлов MP3 (44.1/128) c эфира популярной тематической радиостанции.

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

Но, т.к. даже в тем времена перепрошивка приёмников была не очень доступна «для рядового пользователя» (это у нас, в Чип-Дип(е), продацы узнавали список деталей на распечатке для сборки BDM адаптера первичной перешивки). То компанией было «одобрено» направление по использованию ТВ карт (тюнеров) для установки в ПК.

Разумеется пошли «завлекалочки/улучшения»


Понятно что «односторонняя» передача файлов могла быть омрачена ошибками, поэтому спустя некоторое время появился и «корректирующий» сервис FixDiff (но уже с использованием 2х стороннего интернета и группы энтузиастов).
Screens менюшек программы

На волне энтузиазма, в Мюнхене была создана компания Music Pl@y, которая подружилась с вещателем NBC, и начала передавать свой поток (UpLink в районе Дюссельдорф-а) с одного из транспондеров NBC весной 2000 года. Официальная информация говорила о том, что вещание идёт в «служебных полях» телетекста (оставим это «как есть»).

Тематические «интервалы» были такими:

Спойлер с темами
80е

90е

Chillout

Clubbing

HipHop

Rock — It !

Schmuse (в вольном переводе с немецкого — «обнимашки» (18+))

TOP-50



Помимо «просто треков», вещатель ввёл и передачу подборок — «MegaCD»

По смыслу, это были некоторые сборники «the Best», за год таких «подборок» создавалось около 140.

Через год, эта R@dio.MP3 подала иск о банкротстве (финансирование шло только на доход от рекламы, которое не выдало ожидаемой прибыли). И её начинание, через какое то время перехватила следующая компания — Megaradio.

Поначалу вещание шло в радиоэфире (наземном), потоковом стриминге (www) и через спутник.
Увы, но к этому времени, определённые структуры распознали потенциал и угрозу от «неконтролируемого» распространения mp3 файлов. И вещатель был вынужден довольно заметно изменить политику вещания. Вещание через спутник стало платным, часть сервисов выделили в отдельные предложение Meg@radio.MP3 (например платным по подписке, стало скачать то, что передавалось в текущем эфире). Ну а скачивание «MegaCD» стало стоить отдельных 5Euro (пишу по памяти, возможно немного путаю детали).

В интернете об этом времени/событии информации почти нет.

Есть страничка на немецкой Wiki:

переход на WIKI DE

Существует «страничка памяти» (R@dio.MP3)

переход на сайт

+ некоторую инф. о тех временах (точнее приёмнике от Nokia) можно почитать на:
Сайте "Компьютерпресс"

переход на «Компьютерпресс»

Архивном сайте журнала Телесплетник Телеспутник
переход на «Телеспутник»

Promo треки можно прослушать на YandexДиске (там же лежат пары html/xls списков MegaCD за 2000 и 2001 год) + pdf_ка рекламного буклета R@dio.MP3)
Папка Я-Диск

Let's block ads! (Why?)

NVIDIA показала GPU на Ampere для облачных вычислений и обучения систем на ИИ

image

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

Презентация прошла необычным образом. Директор компании Дженсен Хуанг вынул cистему DGX A100 из духовки у себя на кухне.


«Это наш самый лучший графический процессор для дата-центров, и он вобрал почти десять лет нашего опыта», — отметил Хуанг позднее уже на пресс-конференции.

У GА100 свыше 54 млрд транзисторов. GPU GA100 содержит 8192 ядра CUDA и 512 тензорных ядер третьего поколения, а также шесть модулей памяти HBM2 с шиной памяти разрядностью в 6144 бита. Выпускается по 7-нм технологии компанией TSMC.

A100 GPU при этом — не графический процессор, а графический ускоритель. Он включает пять модулей HBM2 (40 ГБ) с шиной памяти разрядностью в 5120 бит. 3456 ядер CUDA предназначены для вычислений с плавающей запятой двойной точности (FP64), 6912 ядер — для одинарной (FP32). Тензорных ядер третьего поколения с поддержкой вычислений TF32 — 432.

В новой станции DGX A100 AI восемь таких процессоров объединят в один. Общая производительность системы составит 5 петафлопс. Она будет иметь 320 ГБ видеопамяти с пропускной способностью 12,4 Тбит/с.

В GPU включили TensorFloat-32 — новый режим для обработки математических матриц, также называемый тензорными операциями, который используется в основе AI и некоторых приложений HPC. Комбинация TF32 со структурированной разреженностью позволяет повысить производительность процессоров по сравнению с GPU Volta в 20 раз.

image

Пиковая производительность ускорителя составляет 19,5 TFLOPS (FP32) или 9,7 TFLOPS (FP64).

GA100 поддерживает интерфейс NVLink третьего поколения. Это дает возможность обмениваться данными с аналогичными GPU со скоростью 600 Гбайт/с. Каждый графический процессор поддерживает 12 каналов NVLink 3.0. С помощью технологии виртуализации MIG можно разделять ресурсы одного графического процессора на семь независимых сегментов.

image

Разработка будет выполнять задачи обучения искусственного интеллекта. Как отметили в NVIDIA, сейчас клиенты использует решение стоимостью $11 млн, которое занимает 25 серверных стоек в дата-центре и потребляет 630 киловатт электроэнергии. Однако на базе Ampere для тех же мощностей понадобится в 11 раз меньше оборудования, стоимость которого составит около $1 млн, всего одна серверная стойка и 28 киловатт электроэнергии. В компании подчеркнули, что использование новой системы ускорит процесс обучения ИИ в 20 раз.

Серийное производство DGX A100 уже стартовало. В числе заказчиков оказалась Аргоннская национальная лаборатория США, которая планирует задействовать систему в исследованиях коронавируса.

Начальная цена вычислительной станции составляет $199 000.


Nvidia показала также кластер из 140 DGX A100 под названием DGX SuperPod. Он имеет производительность 700 петафлопс. Благодаря соединению с серверными адаптерами Mellanox HDR 200Gbps InfiniBand interconnects компании удалось получить собственный суперкомпьютер. Его можно задействовать в исследованиях генома и разработке говорящих ИИ.

При этом никаких официальных данных о сроках доступности игровых видеокарт с архитектурой Ampere нет.

См. также:

Let's block ads! (Why?)

[Перевод] Что лучше: подтверждение действия или возможность его отмены?

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

Чаще всего эту проблему решают, предусматривая показ диалогового окна для подтверждения действия, и этим ограничиваются. Если выполняемое действие может привести к серьёзным последствиям, то пользователь прочтёт сообщение, выведенное в окне, и, если он стремился сделать именно то, что сделал, подтвердит это действие. Правильно?

Несмотря на популярность вышеописанного механизма, использование диалогового окна подтверждения действия — это, в 90% случаев, неправильно. Поговорим о том, почему это так.

Проблемы диалоговых окон подтверждения действий


Вот некоторые проблемы, сопровождающие применение механизмов подтверждения действий пользователей:
  • Эти механизмы прерывают работу пользователя. Идея, которая лежит в основе применения диалоговых окон для подтверждения действий, заключается в том, чтобы остановить работу пользователя. Это должно дать ему возможность подумать о последнем совершённом действии и понять — действительно ли он сделал именно то, что намеревался. Но проблема прерывания работы пользователя заключается в том, что это отвлекает его от того, что он пытался сделать. Появление диалогового окна принуждает пользователей перестать думать о том, что они делают. Они, вместо этого, пытаются понять новую информацию.
  • Мы, по привычке, нажимаем на кнопку, подтверждающую выполнение действия. Человек формирует сотни привычек, которые помогают ему жить. Одна из таких привычек заключается в том, что когда мы видим диалоговое окно, предлагающее что-то подтвердить, мы очень быстро его закрываем, не особенно вглядываясь в его содержимое. Привычку быстрого закрытия диалоговых окон закрепляет ещё и то, что в современном интернете каждый владелец сайта считает своим долгом показать посетителю всплывающее окно с предложением зарегистрироваться. 
  • Мы не читаем тексты, выводимые в диалоговых окнах, предназначенных для подтверждения действий. Даже если человек и прочитает текст в подобном окне, он не всегда даёт себе возможность остановиться и подумать о прочитанном. Если не происходит ничего экстраординарного, мы полагаем, что всё идёт как надо, и нажимаем на кнопку подтверждения действия просто из-за того, что она позволяет убрать маленькое окно, которое перекрывает то, чем мы сейчас занимаемся. Главная кнопка в любом подобном окне немедленно воспринимается как кнопка, которая позволяет пользователю продолжить заниматься тем, чем он занимался.

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

Сильные стороны механизмов отмены действий


Вот некоторые сильные стороны средств, позволяющих отменять действий:
  • Эти средства создают, исходя из предположения о том, что пользователь уверен в том, что он делает. Главное преимущество средств отмены действий перед окнами подтверждения заключается в том, что система не пытается предсказать действия пользователя. Нечто вроде кнопки отмены просто решает свою задачу, не задавая пользователю вопросов о том, уверен ли он в выполняемом действии.
  • Механизмы отмены действий не мешают работе пользователя. Избавление от окна подтверждения действия и замена его менее заметным элементом управления, служащим для отмены изменений, позволяет не прерывать работу пользователя и не отвлекать его от решаемых им задач. Кнопка для отмены изменений — это не совершенно новый интерфейс, появляющийся перед пользователем и требующий внимания к себе.
  • Средства отмены действий помогают пользователям исследовать программы. Если у пользователя есть возможность отменять действия, это его поддерживает, говоря ему о том, что он не может что-либо непоправимо испортить. Мне часто доводилось слышать рассказы не особенно продвинутых пользователей ПК о том, что они не пытаются работать с неизвестными элементами интерфейсов приложений из-за того, что не хотят что-то испортить.
  • Использование механизмов отмены действий позволяет пользователям самим видеть результаты своей работы, а не читать об этом. Иногда пользователи не уверены на 100% в том, что их действия приведут именно к тем результатам, к которым они стремятся. Наличие в приложении чего-то вроде кнопки отмены действия позволяет пользователю видеть результаты своих действий и результаты их отмены. Это помогает пользователю определиться с тем, внёс ли он в систему именно то изменение, которое хотел внести.

Эффективное использование механизмов отмены изменений


Итак, если возможность отмены изменений — это очень хорошо, давайте подумаем о том, как лучше всего реализовать в приложении подобную возможность. Вот некоторые идеи, касающиеся реализации качественного механизмы отмены изменений:
  • Давайте пользователю обратную связь. Если пользователь не видит результатов того, что сделал, то возможность отменить это действие не так уж и важна. Поэтому давайте пользователю обратную связь. Позвольте ему увидеть результаты совершённого им действия. Например — если в OS X файл отправляют в корзину — это сопровождается звуковой и визуальной обратной связью.
  • Сделайте элемент управления, позволяющий отменить действие, хорошо заметным. Если удалять что-либо в вашей программе — это обычное дело (скажем — при работе с некими списками), разместите элемент управления для отмены действия прямо рядом с удалённым элементом. Если отмена действия может понадобиться не особенно часто — то хорошим вариантом будет показ всплывающей подсказки в верхней или в нижней части экрана. Например, именно так сделано в Gmail. Там, в верхней части экрана, показывают жёлтый баннер, содержащий ссылку для отмены действия.


Предложение об отмене действия в Gmail
  • Сделайте так, чтобы элементы можно было бы восстанавливать. Создайте в своей программе место, куда попадают удалённые элементы и не уничтожайте их безвозвратно. Местом хранения удалённых элементов может быть нечто вроде корзины, архива, папки «Исходящие сообщения». Подобная стратегия используется в Trello, где карточки не удаляются, а, вместо этого, архивируются. Если пользователь хочет восстановить карточку, он может перейти в архив и сделать это, вернув её туда, где она была.
  • Откладывайте выполнение необратимых действий. Если действие, которое выполнил пользователь, нельзя отменить — откладывайте его выполнение. Например, в Gmail есть возможность откладывания отправки писем на 15 секунд.

Что если отменить действие невозможно?


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

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

  • Постарайтесь, чтобы диалоговые окна появлялись бы только в особых случаях. Лучший способ повысить эффективность использования диалоговых окон — сделать так, чтобы они появлялись бы не особенно часто.

Вот что написано по этому поводу в книге «Алан Купер об интерфейсе. Основы проектирования взаимодействия», в разделе «Диалоговое окно, которое кричало: «Волк!» (Купер А., Рейман Р., Кронин Д. Алан Купер об интерфейсе. Основы проектирования взаимодействия. – Пер.с англ. – СПб.: Символ-Плюс, 2009. – 688 с., ил.):

Подтверждения иллюстрируют интересный парадокс человеческой психики: они срабатывают, только если их не ожидают. Это обстоятельство не кажется важным, пока вы не изучите контекст. Если запрашивать подтверждение в обычных ситуациях, пользователь быстро привыкает к таким диалоговым окнам и выдаёт подтверждение не глядя. Подобная реакция становится делом столь же обычным, как появление самих диалоговых окон. Если в какой-то момент возникнет действительно неожиданная и опасная ситуация, к которой следует привлечь внимание пользователя, пользователь просто в силу привычки по-быстрому расправится с подтверждением. Подобно мальчику из притчи, который кричал: «Волк!», – диалоговое окно подтверждения не подействует в случае реальной опасности, потому что оно слишком много раз кричало, когда никакой опасности не было.

Чтобы диалоговые окна подтверждения работали, они должны появляться в тех случаях, когда пользователь почти наверняка щёлкнет по кнопке Нет или Отмена, и они ни в коем случае не должны появляться тогда, когда пользователь скорее щелкнет по кнопке Да или ОК.

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


Необычный способ подтверждения удаления репозитория
  • Используйте понятные надписи на кнопках. Сделайте так, чтобы на кнопке подтверждения было бы чётко описано выполняемое по её нажатию действие. Не стоит писать на таких кнопках что-то вроде Да или Подтвердить. Более вероятно то, что пользователь щёлкнет по кнопке Подтвердить, чем по кнопке, на которой написано Удалить kittens.jpg.

Используете ли вы окна подтверждения действий в своих проектах?

Let's block ads! (Why?)

Samsung прекращает поддержку своей платформы виртуальной реальности XR


Компания Samsung объявила, что прекращает поддержку своей платформы виртуальной реальности XR. Доступ к ней будет полностью закрыт для пользователей 30 сентября 2020 года.
Процедуру отказа от собственной платформы виртуальной реальности XR Samsung разделила на несколько этапов, которые будут вместе длиться в течение четырех с половиной месяцев. Это сделано для того, чтобы пользователи смогли сохранить свои данные и были в курсе происходящего.

Так с 11 мая 2020 года пользователи виртуального сервиса компании и приложений Samsung XR и Samsung VR Video перестали получать обновления и не могут больше загружать в VR-приложения свои 360-градусные видеоролики, так как теперь в Samsung XR отключена функция «Загрузка видео». Дополнительно с этого момента для пользователей отключена функция Creator Portal Analytics.

С 30 июня 2020 года Samsung прекратит поддержку приложения Samsung VR Video на устройствах виртуальной реальности Oculus Go, Oculus Rift или Oculus Quest. Вдобавок компания удалит приложение Samsung VR Video из магазина Oculus.

Далее через два месяца с 30 сентября 2020 года Samsung отключит и безвозвратно удалит все учетные записи пользователей сервиса Samsung XR. С этого момента пользователи больше не смогут войти в Samsung XR для просмотра своего контента. Также компания удалит из сервиса Samsung XR все опубликованные пользователями ранее видеоролики. Доступ к этим записям, размещенным на сайте www.samsungxr.com с помощью встроенной ссылки, будет заблокирован.

В конце сентября 2020 года приложение Samsung VR Video больше не будет поддерживаться устройствами Samsung Gear VR и Windows Odyssey. Компания удалит приложение Samsung VR Video из магазина Microsoft Mixed Reality. Тоже произойдет и с мобильным приложением Samsung XR — оно не будет больше поддерживаться на устройствах Android и будет удалено из магазинов Galaxy Store и Google Play.

Samsung не объяснила причину своих деструктивных действий по этому ранее интересному компании направлению. Хотя в последнее время Samsung прекратила выпускать новые версии гарнитуры Gear VR и охладела к этому сегменту рынка.

Ранее в конце марта 2020 года компания Oculus прекратила поддержку своих приложений Oculus 360 Photos, Oculus Video и Oculus Browser для устройств виртуальной реальности Samsung Gear VR.

Let's block ads! (Why?)

[Из песочницы] Пишем автотест с использованием Selenium Webdriver, Java 8 и паттерна Page Object

В этой статье рассматривается создание достаточного простого автотеста. Статья будет полезна начинающим автоматизаторам.

Материал изложен максимально доступно, однако, будет значительно проще понять о чем здесь идет речь, если Вы будете иметь хотя бы минимальные представления о языке Java: классы, методы, etc.

Нам понадобятся:


  • установленная среда разработки Intellij IDEA (является самой популярной IDE, для большинства случаев достаточно бесплатной версии Community Edition);
  • установленные Java (jdk/openjdk) и Maven, прописанные в системные окружения ОС;
  • браузер Chrome и chromedriver — программа для передачи команд браузеру.

Создание проекта

Запустим Intellij IDEA, пройдем первые несколько пунктов, касающихся отправки статистики, импорта проектов, выбора цветовой схемы и т.д. — просто выберем параметры по умолчанию.

В появившемся в конце окне выберем пункт «Create New Project», а в нем тип проекта Maven. Окно будет иметь вид:

image


  • Maven — это инструмент сборки Java проектов;
  • Project SDK — версия Java, которая установлена на компьютере;
  • Create from archetype — это возможность создавать проект с определенным архетипом (на данном этапе данный чекбокс отмечать не нужно).

Нажмем «Next». Откроется следующее окно:

image

Groupid и Artifactid — идентификаторы проекта в Maven. Существуют определенные правила заполнения этих пунктов:


  • Groupid — название организации или подразделения занимающихся разработкой проекта. В этом пункте действует тоже правило как и в именовании пакетов Java: доменное имя организации записанное задом наперед. Если у Вас нет своего доменного имени, то можно использовать свой э-мейл, например com.email.email;
  • Artifactid — название проекта;
  • Version — версия проекта.

Нажмем «Finish»: IDE автоматически откроет файл pom.xml:

image

В нем уже появилась информация о проекте, внесенная на предыдущем шаге: Groupid, Artefiactid, Version. Pom.xml — это файл который описывает проект. Pom-файл хранит список всех библиотек (зависимостей), которые используются в проекте.

Для этого автотеста необходимо добавить две библиотеки: Selenium Java и Junit. Перейдем на центральный репозиторий Maven mvnrepository.com, вобьем в строку поиска Selenium Java и зайдем в раздел библиотеки:

image

Выберем нужную версию (в примере будет использована версия 3.14.0). Откроется страница:

image

Копируем содержимое блока «Maven» и вставим в файл pom.xml в блок

<dependencies> </dependencies>

Таким образом библиотека будет включена в проект и ее можно будет использовать. Аналогично сделаем с библиотекой Junit (будем использовать версию 4.12).

Итоговый pom-файл:

image


Создание пакета и класса

Раскроем структуру проекта. Директория src содержит в себе две директории: «main» и «test». Для тестов используется, соответственно, директория «test». Откроем директорию «test», кликом правой клавиши мыши по директории «java» выберем пункт «New», а затем пункт «Package». В открывшемся диалоговом окне необходимо ввести название пакета. Имя базового пакета должно носить тоже имя, что и Groupid — «org.example».

Следующий шаг — создание класса Java, в котором пишется код автотеста. Кликом правой клавиши мыши по названию пакета выберем пункт «New», а затем пункт «Java Class».

В открывшемся диалоговом окне необходимо ввести имя Java класса, например, LoginTest (название класса в Java всегда должно начинаться с большой буквы). В IDE откроется окно тестового класса:

image


Настройка IDE

Прежде чем начать, необходимо настроить IDE. Кликом правой клавиши мыши по названию проекта выберем пункт «Open Module Settings». В открывшемся окне во вкладке «Sources» поле «Language level» по умолчанию имеет значение 5. Необходимо изменить значение поля на 8 (для использования всех возможностей, присутствующих в этой версии Java) и сохранить изменения:

image

Далее необходимо изменить версию компилятора Java: нажмем меню «File», а затем выберем пункт Settings.

В открывшемся перейдем «Build, Execution, Deployment» -> «Compiler» -> «Java Compiler». По умолчанию установлена версия 1.5. Изменим версию на 8 и сохраним изменения:

image


Test Suite

Описание:


  1. Пользователь открывает страницу аутентификации;
  2. Пользователь производит ввод валидных логина и пароля;
  3. Пользователь удостоверяется в успешной аутентификации — об этом свидетельствует имя пользователя в верхнем правом углу окна;
  4. Пользователь осуществляет выход из аккаунта путем нажатия на имя пользователя в верхнем правом углу окна с последующим нажатием на кнопку «Выйти…».

Тест считается успешно пройденным в случае, когда пользователю удалось выполнить все вышеперечисленные пункты.

Для примера будет использоваться аккаунт Яндекс (учетная запись заранее создана вручную).


Первый метод

В классе LoginTest будет описана логика теста. Создадим в этом классе метод «setup()», в котором будут описаны предварительные настройки. Итак, для запуска браузера необходимо создать объект драйвера:

WebDriver driver = new ChromeDriver();

Перед созданием объекта WebDriver следует установить зависимость, определяющую путь к chomedriver (в ОС семейства Windows дополнительно необходимо указывать расширение .exe):

System.setProperty("webdriver.chrome.driver", "/usr/bin/chromedriver");

Чтобы ход теста отображался в полностью открытом окне, необходимо сказать об этом драйверу:

driver.manage().window().maximaze();

Случается, что элементы на страницах доступны не сразу, и необходимо дождаться появления элемента. Для этого существуют ожидания. Они бывают двух видов: явные и неявные. В примере будет использовано неявное ожидание Implicitly Wait, которое задается вначале теста и будет работать при каждом вызове метода поиска элемента:

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

Таким образом, если элемент не найден, то драйвер будет ждать его появления в течении заданного времени (10 секунд) и шагом в 500 мс. Как только элемент будет найден, драйвер продолжит работу, однако, в противном случае тест упадем по истечению времени.

Для передачи драйверу адреса страницы используется команда:

driver.get("https://passport.yandex.ru/auth")

Выносим настройки

Для удобства вынесем название страницы в отдельный файл (а чуть позже и некоторые другие параметры).

Создадим в каталоге «test» еще один каталог с названием «resources», а в нем обычный файл «conf.properties», в который поместим переменную:

loginpage = https://passport.yandex.ru/auth

а также внесем сюда путь до драйвера

chromedriver = /usr/bin/chromedriver

image

В пакете «org.example» создадим еще один класс «ConfProperties», который будет читать записанные в файл «conf.properties» значения:

image

package org.example;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class ConfProperties {
    protected static FileInputStream fileInputStream;
    protected static Properties PROPERTIES;
    static {
        try {
            //указание пути до файла с настройками
            fileInputStream = new FileInputStream("src/test/resources/conf.properties");
            PROPERTIES = new Properties();
            PROPERTIES.load(fileInputStream);
        } catch (IOException e) {
            e.printStackTrace();
            //обработка возможного исключения (нет файла и т.п.)
        } finally {
            if (fileInputStream != null)
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace(); } } }
    /**
     * метод для возврата строки со значением из файла с настройками
     */
    public static String getProperty(String key) {
        return PROPERTIES.getProperty(key); } }

Обзор первого метода

image

Метод «setup()» пометим аннотацией Junit «@BeforeClass», которая указывает на то, что метод будет выполняться один раз до выполнения всех тестов в классе. Тестовые методы в Junit помечаются аннотацией Test.

package org.example;
import org.junit.BeforeClass;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.concurrent.TimeUnit;
public class LoginTest {
    /**
     * осуществление первоначальной настройки
     */
    @BeforeClass
    public static void setup() {
        //определение пути до драйвера и его настройка
        System.setProperty("webdriver.chrome.driver", ConfProperties.getProperty("chromedriver"));
        //создание экземпляра драйвера
        WebDriver driver = new ChromeDriver();
        //окно разворачивается на полный экран
        driver.manage().window().maximize();
        //задержка на выполнение теста = 10 сек.
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        //получение ссылки на страницу входа из файла настроек
        driver.get(ConfProperties.getProperty("loginpage")); } }

Page Object

При использовании Page Object элементы страниц, а также методы непосредственного взаимодействия с ними, выносятся в отдельный класс.

Создадим в пакете «org.example» класс LoginPage, который будет содержать локацию элементов страницы логина и методы для взаимодействия с этими элементами.

Откроем страницу авторизации в сервисах Яндекс (https://passport.yandex.ru/auth) в браузере Chrome. Для определения локаторов элементов страницы, с которыми будет взаимодействовать автотест, воспользуемся инструментами разработчика. Кликом правой кнопки мыши вызовем меню «Просмотреть код». В появившейся панели нажмем на значок курсора (левый верхний угол панели разработчика) и наведем курсор на интересующий нас элемент — поле ввода логина.

В результате мы увидим этот элемент среди множества других. Теперь мы можем скопировать его локацию. Для этого кликаем правой кнопкой мыши по выделенному в панели разработчика элементу, выбираем меню «Copy» -> «Copy XPath».

//*[@id="root"]/div/div/div[2]/div/div/div[3]/div[2]/div/div/div[1]/form/div[1]/div[1]/label

Для локации элементов в Page Object используется аннотация @FindBy.

Напишем следующий код:

@FindBy(xpath = "//*[@id="root"]/div/div/div[2]/div/div/div[3]/div[2]/div/div/div[1]/form/div[1]/div[1]/label")
private WebElement loginField;

Таким образом мы нашли элемент на страницу и назвали его loginField (элемент доступен только внутри класса LoginPage, т.к. является приватным).

Однако, такой длинный и страшный xpath использовать не рекомендуется (рекомендую к прочтению статью «Не так страшен xpath как его незнание». Если присмотреться, то можно увидеть, что поле ввода логина имеет уникальный id:

image

Воспользуемся этим и изменим поиск элемента по xpath:

@FindBy(xpath = "//*[contains(@id, 'passp-field-login')]")

Теперь вероятность того, что поле ввода пароля будет определено верно даже в случае изменения местоположения элемента на странице, возросла.

Аналогично изучим следующие элементы и получим их локаторы.

Кнопка «Войти»:

@FindBy(xpath = "//*[contains(text(), 'Войти')]")
private WebElement loginBtn;

Поле ввода пароля:

@FindBy(xpath = "//*[contains(@id, 'passp-field-passwd')]")
private WebElement passwdField;

А теперь напишем методы для взаимодействия с элементами.

Метод ввода логина:

public void inputLogin(String login) {
        loginField.sendKeys(login); }

Метод ввода пароля:

public void inputPasswd(String passwd) {
        passwdField.sendKeys(passwd); }

Метод нажатия кнопки входа:

public void clickLoginBtn() {
        loginBtn.click(); }

Для того, чтобы аннотация @FindBy заработала, необходимо использовать класс PageFactory. Для этого создадим конструктор и передадим ему в качестве параметра объект Webdriver:

public WebDriver driver;
public LoginPage(WebDriver driver) {
        PageFactory.initElements(driver, this);
        this.driver = driver; }

image

package org.example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class LoginPage {
    /**
     * конструктор класса, занимающийся инициализацией полей класса
     */
    public WebDriver driver;
    public LoginPage(WebDriver driver) {
        PageFactory.initElements(driver, this);
        this.driver = driver; }
    /**
     * определение локатора поля ввода логина
     */
    @FindBy(xpath = "//*[contains(@id, 'passp-field-login')]")
    private WebElement loginField;
    /**
     * определение локатора кнопки входа в аккаунт
     */
    @FindBy(xpath = "//*[contains(text(), 'Войти')]/..")
    private WebElement loginBtn;
    /**
     * определение локатора поля ввода пароля
     */
    @FindBy(xpath = "//*[contains(@id, 'passp-field-passwd')]")
    private WebElement passwdField;
    /**
     * метод для ввода логина
     */
    public void inputLogin(String login) {
        loginField.sendKeys(login); }
    /**
     * метод для ввода пароля
     */
    public void inputPasswd(String passwd) {
        passwdField.sendKeys(passwd); }
    /**
     * метод для осуществления нажатия кнопки входа в аккаунт
     */
    public void clickLoginBtn() {
        loginBtn.click(); } }

После авторизации мы попадаем на страницу пользователя. Т.к. это уже другая страница, в соответствии с идеологией Page Object нам понадобится отдельный класс для ее описания. Создадим класс ProfilePage, в котором определим локаторы для имени пользователя (как показателя успешного входа в учетную запись), а также кнопки выхода из аккаунта. Помимо этого, напишем методы, которые будут получать имя пользователя и нажимать на кнопку выхода.

Итого, страница ввода логина будет иметь следующий вид:

image

package org.example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class ProfilePage {
    /**
     * конструктор класса, занимающийся инициализацией полей класса
     */
    public WebDriver driver;
    public ProfilePage(WebDriver driver) {
        PageFactory.initElements(driver, this);
        this.driver = driver; }
    /**
     * определение локатора меню пользователя
     */
    @FindBy(xpath = "//*[contains(@class, 'account__name_hasAccentLetter')]")
    private WebElement userMenu;
    /**
     * определение локатора кнопки выхода из аккаунта
     */
    @FindBy(xpath = "//*[contains(@class, 'menu-item_action_exit menu__item menu__item_type_link')]")
    private WebElement logoutBtn;
    /**
     * метод для получения имени пользователя из меню пользователя
     */
    public String getUserName() {
        String userName = userMenu.getText();
        return userName; }
    /**
     * метод для нажатия кнопки меню пользователя
     */
    public void entryMenu() {
        userMenu.click(); }
    /**
     * метод для нажатия кнопки выхода из аккаунта
     */
    public void userLogout() {
        logoutBtn.click(); } }

Интересный момент: в метод getUserName() пришлось добавить еще одно ожидание, т.к. страница «тяжелая» и загружалась довольно медленно. В итоге тест падал, потому что метод не мог получить имя пользователя. Метод getUserName() с ожиданием:

public String getUserName() {
        WebDriverWait wait = new WebDriverWait(driver, 10);
        wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(@class, 'account__name_hasAccentLetter')]")));
        String userName = userMenu.getText();
        return userName; }

Вернемся к классу LoginTest и добавим в него созданные ранее классы-страницы путем объявления статических переменных с соответствующими именами:

public static LoginPage loginPage;
public static ProfilePage profilePage;

Сюда же вынесем переменную для драйвера

public static WebDriver driver;

В аннотации @BeforeClass создаем экземпляры классов созданных ранее страниц и присвоим ссылки на них. Создание экземпляра происходит с помощью оператора new. В качестве параметра указываем созданный перед этим объект driver, который передается конструкторам класса, созданным ранее:

loginPage = new LoginPage(driver);
profilePage = new ProfilePage(driver);

А создание экземпляра драйвера приведем к следующему виду (т.к. он объявлен в качестве переменной):

driver = new ChromeDriver();

Тест

Теперь можно перейти непосредственно к написанию логики теста. Создадим метод loginTest() и пометим его соответствующей аннотацией:

@Test
    public void loginTest() {
        //значение login/password берутся из файла настроек по аналогии с chromedriver
//и loginpage
//вводим логин
        loginPage.inputLogin(ConfProperties.getProperty("login"));
    //нажимаем кнопку входа
        loginPage.clickLoginBtn();
    //вводим пароль
        loginPage.inputPasswd(ConfProperties.getProperty("password"));
    //нажимаем кнопку входа
        loginPage.clickLoginBtn();
        //получаем отображаемый логин
        String user = profilePage.getUserName();
    //и сравниваем его с логином из файла настроек
        Assert.assertEquals(ConfProperties.getProperty("login"), user); }

Осталось лишь корректно все завершить. Создадим финальный метод и пометим его аннотацией @AfterClass (методы помеченные этой аннотацией выполняются один раз, после завершения всех тестовых методов класса).

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

@AfterClass
    public static void tearDown() {
        profilePage.entryMenu();
        profilePage.userLogout();
        driver.quit(); }

Последняя строка нужна для закрытия окна браузера.


Обзор теста

Итого, имеем:

package org.example;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.concurrent.TimeUnit;
public class LoginTest {
    public static LoginPage loginPage;
    public static ProfilePage profilePage;
    public static WebDriver driver;

    /**
     * осуществление первоначальной настройки
     */
    @BeforeClass
    public static void setup() {
        //определение пути до драйвера и его настройка
        System.setProperty("webdriver.chrome.driver", ConfProperties.getProperty("chromedriver"));
        //создание экземпляра драйвера
        driver = new ChromeDriver();
        loginPage = new LoginPage(driver);
        profilePage = new ProfilePage(driver);
        //окно разворачивается на полный экран
        driver.manage().window().maximize();
        //задержка на выполнение теста = 10 сек.
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        //получение ссылки на страницу входа из файла настроек
        driver.get(ConfProperties.getProperty("loginpage")); }
    /**
     * тестовый метод для осуществления аутентификации
     */
    @Test
    public void loginTest() {
        //получение доступа к методам класса LoginPage для взаимодействия с элементами страницы
        //значение login/password берутся из файла настроек по аналогии с chromedriver
        //и loginpage
        //вводим логин
        loginPage.inputLogin(ConfProperties.getProperty("login"));
        //нажимаем кнопку входа
        loginPage.clickLoginBtn();
        //вводим пароль
        loginPage.inputPasswd(ConfProperties.getProperty("password"));
        //нажимаем кнопку входа
        loginPage.clickLoginBtn();
        //получаем отображаемый логин
        String user = profilePage.getUserName();
        //и сравниваем его с логином из файла настроек
        Assert.assertEquals(ConfProperties.getProperty("login"), user); }
    /**
     * осуществление выхода из аккаунта с последующим закрытием окна браузера
     */
    @AfterClass
    public static void tearDown() {
        profilePage.entryMenu();
        profilePage.userLogout();
        driver.quit(); } }

Запуск автотеста

Для запуска автотестов в Intellij Idea имеется несколько способов:


  • Alt+Shift+F10;
  • Клик правой клавишей мышки по имени тестового класса, после чего в открывшемся меню выбрать Run;

В результате выполнения автотеста, в консоли Idea я вижу, что тестовый метод loginTest() пройден успешно:

image

Let's block ads! (Why?)