среда, 20 декабря 2017 г.

резюме по первому блоку с базовыми командами в Selenium



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

Новая страница открывается с помощью команды get, которая иногда принимает более длинную форму navigate to().
Чтобы выполнить какое-то действие с элементом, надо его сначала найти. Для этого используется команда findElement, которая возвращает объект, являющийся представителем реального элемента, находящегося на странице. Как только реальный элемент на странице пропадает, такие действия через его представителя уже совершить нельзя. При попытке выполнить любое действие возникает исключение staleElementsReferentsExcepiton, чи как-то так.
2 ключевые команды, которые можно выплонять с элементами, предназначены для симуляции действия мыши и клавиатуры.
Важное правило - С. выполняет действия только с теми элементами, которые видны в браузере. Кликать по невидимым элементам и заполнять скрытые поля ввода запрещено. При попытке сделать такое, выбрасывается исключение.
В конце сценария автоматизации надо вызывать метод quit. Чтобы остановить все запущенные процессы. И браузер, и вспомогательный исполняемый файл и освободить все захваченные ресурсы.
Если этод метод не вызвать, то в некоторых случаях ЯП сам справится с решением задачи, но это происходит не всегда.


Единообразие во всех языках



обратить внимание на названия.
get, findElement, sendKeys, click, quit.
Они везде одинаковые, отличаются только от договоренностей. Например, в некоторых ЯП юзают вместо кэмел-кейса нижнее подчеркивание, где-то с большой буквы названия методов и т.п.


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

вторник, 19 декабря 2017 г.

Selenium, разбор кода




Итак, сначала мы объявляем переменную
mainMenu и запиливаем туда массив из названий категорий: "Снова в продаже, "Новые товары" и т.д.
subMenu - это для следующего теста.
Дальше мы делаем цикл:


Внутри цикла объявляем переменную х = 1, потом пишем условие, что пока x<= 13(количество категорий), перебирать категории х++)
В общем, пока х больше или равно 13, мы переходим по категориям и выполняем функцию(?) makeSubElementsTest(x);


В функции мы пишем тест

it('Все категории: категория: ' + mainMenu[x - 1], function () {
В параметрах функции выводится название: "Все категории: категория: ' + mainMenu[x - 1] т.е. название
категории, например, "Снова в продаже"), вторым аргументом функции еще одна 
функция, пустая function (). 


понедельник, 18 декабря 2017 г.

Действия с элементами

2 устройства взаимодействия:
- мышь;
- клава.
2 основные команды, которые мы юзаем:
- клик (мышь);
- send keys (ввод с клавы)












Команда findElement позволяет нам найти поле ввода, возвращается объект, который соответствует этому найденному элементу и у этого объекта вызывается метод sendKeys - ввод текста в это поле ввода.
Далее находим элемент, который соответсвует кнопке и команда .click симулирует нажатие кнопки мыши.
2 важных правила:
1. Элемент должен присутствовать на странице. Если между поиском элемента и использованием этого элемента (перед выполнением sendKeys или click) прошло много времени и может быть выполнялись какие-то другие действия, страница могла обновиться. Тогд этот элемент мог с нее исчезнуть. Даже если вместо него есть другой элемент с таким же локатором, это для него уже другой элемент, не тот же самый. И при попытке выполнить sendKeys или click для исчезнувшего элемента возникнет ошибка stalereference... exception. Искать элементы надо непосредственно перед тем, как мы его будем юзать.
Так что чаще всего в нашем коде будут встречаться именно такие цепочки из двух команд: 
findElement, затем sendKeys
findElement, затем click или какое-то другое действие с найденным элементом.

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

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

  

воскресенье, 10 декабря 2017 г.

Заметки по тестированию, примерный разбор кода



it('Кнопка наверх', function(){
    let testResult = true;
    return this.browser        
.url('/')
        .isExisting('.footer__back-top .button_view_plain')
        .then(result=> assert.isTrue(result,'.footer__back-top .button_view_plain - не существует'),(err)=> {console.log(err); testResult = false})
        .getText('.footer__back-top .button_view_plain')
        .then(text => assert.isTrue(text === 'наверх', text+' != "наверх"'),(err)=> {console.log(err); testResult = false})
        .isExisting('.footer__back-top .icon svg path')
        .then(result =>; assert.isTrue(result, 'иконка не существует'),(err)=> {console.log(err); testResult = false})
        .click('.footer__back-top .button_view_plain')
        .then(() => assert.isTrue(true),(err)=> {console.log(err); testResult = false})
        .isVisible('.header__logo')
        .then(result => assert.isTrue(result, 'логотип не виден'),(err)=> {console.log(err); testResult = false})
        .then(()=> assert.isTrue(testResult))
});



it('Кнопка наверх', function(){  - типа, название главной функциональности, которую мы проверяем.

let testResult = true; - предположим, что переменная testResult - трушная.

return this.browser  - похоже, что-то для того, чтобы тесты проходили у меня локально на компе, в моем браузере.

.url('/') - проверять по такому-то адресу, там шо-та, видимо, еще в глобальных настройках настроено.

.isExisting('.footer__back-top .button_view_plain') - существует такой-то элемент по такому-то адресу.

.then(result=> assert.isTrue(result,'.footer__back-top .button_view_plain - не существует'),(err)=> {console.log(err); testResult = false})

проверяем, типа, затем переменная "результат", утверждаем, что тру (выводим переменную "результат", если не тру, то такой-то элемент не существует), (err - хз шо это, может, какая-то дефолтовая хрень выводит в консоль эту err; переменная testResult будет равна фолс)
Типа, есичо, если это будет фолсная переменная, она не закрашит систему, а просто отметит в консольке, что там зафейлилось.

.getText('.footer__back-top .button_view_plain') - метод взять текст из такого-то элемента

.then(text => assert.isTrue(text === 'наверх', text+' != "наверх"'),(err)=> {console.log(err); testResult = false})

проверяем, типа, переменная "text" - действительно "наверх", в противном случае выводим, что текст не "наверх", потом
.click('.footer__back-top .button_view_plain') - нажали на элемент
.then(() => assert.isTrue(true),(err)=> {console.log(err); testResult = false}) - 

хрень.

.then(()=> assert.isTrue(testResult)) - предположим, что тру, тогда весь комплект тру.
       
.it - метод, который является тестом.
it('Кнопка наверх', function(){
метод, принимает два параметра: 'Кнопка наверх' - строковое значение (что ттестируем, название теста)
и функцию (сам тест).

let testResult = true; - оператор объявления переменной, действующей внутри блока.
Блок - это код, заключенный в фигурные скобки.

Переменная testResult - булеановская, ей дано значение тру.

return this.browser -  оператор для возврата значения функции, this - указатель на объект
browser - объект

.url('/') - метод .url(с параметром "ссылка"). Этот метод открывает страницу относительно baseUrl
если не указан точный адрес.

.then(result=> assert.isTrue(result,'.footer__back-top .button_view_plain - не существует'),(err)=> {console.log(err); testResult = false})

метод .then(onSuccess, Error)

onSuccess  - данный блок выполняется в случае успеха предыдущей функции.
Error  - выполняется в случае возникновения ошибки в предыдущем блоке.

=> - стрелочная функция (загуглить!)

.then (он в переменную "результат" записывает результат строчки выше, т.е. тру или фолс)
потом => чтобы остаться в пределах then. 
assert - Объект(он объявлен выше, где chai),у которого есть методы:
isTrue()
1. если значение тру - проходит дальше
2. фолс - выводит текст указанный во втором параметре и сфейливается '.footer__back-top .button_view_plain - не существует'






вторник, 5 декабря 2017 г.

Заметки по тестированию, траблшут, с которым столкнулась.

В общем, пишу, ну, как пишу, частично пишу, частично переписываю тесты, которые сделал Никита.
Столкнулась с траблшутом.
У Никиты был такой кусок кода:



В общем, он нажимает на белый текст, шоб исчез попапчик.
Там еще какая-то, кмк, оверлогика была, типа, он сначала нажимает на этот белый текст, потом делает .isExisting и дальше пишет, что атрибут "aria-hidden" элемента popup_target_anchor = true.
И уже потом проверяет, правда ли у этого класса в атрибуте "aria-hidden" значение трушное, т.е. он скрыт, и если элемент и правда скрыт (значение спрятанности трушное), то уже потом выдает результат, мол, да, все норм.
ИМХО, это как-то суперсложно.

У меня долго не получалось, пока не сделала скриншоты происходящего.
Скриншот получился такой:



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


































понедельник, 4 декабря 2017 г.

Поиск элементов

2 сложности:
- no such element exception - не найден.
- stale element reference exception. (stale - устаревший) - потерялся.

Поиск элемента выполняется с помощью команды findElement или findElements.
В качестве параметра эти команды принимают т.н. локатор, описание правил или стратегии поиска элемента(ов).
Например, эта команда найдет элемент, у которого есть атрибут name, имеющий заданное значение. Если на странице несколько таких элементов, значит будет найден первый из них. Когда нас интересует не только первый, а все элементы, надо использовать команду findElements, она возвращает список элементов.
Если по какой-то причине команда findElement не может найти то, о чем попросили, она выбрасывает исключение.



4 причины:
1. Невалидный локатор.
2. Нет такого элемента:
- страница поменялась, изменилась верстка.
- в локаторах использовались какие-то критерии, основанные на изменяющихся свойствах элементов. Например, часто бывает, что id элементов создаются динамически, либо каждый раз они вообще новые, либо заменяются при перекомпиляции целевого приложения. Выпустили разрабы новую версию, а там все локаторы другие.
3. Сейчас нет такого элемента. Мы смотрим - он есть, но в тот момент, когда с.искал элемент, его не было. Скорей всего - надо использовать ожидание, т.е. искать элемент не сразу, а ждать, когда он появится.
4. Элемент может находиться в другом окне или другом фрейме.

findElement - выбрасывает исключение.
findElements - возвращает пустой список.


Посмотрим что возвращает метод findElement.
Поставим точку остановки, запустим сценарий в отладчике и проанализируем содержимое объекта типа WebElement.




Единственное, что хранится внутри этого объекта, это уникальный идентификатор. С. не загружает из браузера никакую инфу об элементах, кроме этого идентификатора. Если надо совершить с элементом какое-то действие или узнать какое-то свойство этого элемента, даже самое простое, например, тег, с. обращается к браузеру. Если мы два раза спросим тег элемента, он будет два раза обращаться к браузеру. Никакого кеширования на стороне клиентской библиотеки нет. Любое действие, любое получение свойства какого-то элемента - это всегда обращение к браузеру.
И при каждом таком обращении С. передает туда этот уникальный id элемента. Внутри браузера все элементы имеют такие уникальные id. Но когда страница меняется, элементы старые исчезают, появляются новые,  у этих элементов будут новые идентификаторы. Даже если новые элементы находятся на том же самом месте, где находились старые элементы и даже если они абсолютно так же выглядят, имеют такой же набор свойств, такой же текст, у них все равно будут новые идентификаторы.
Когда С. обращается к браузеру и передает туда id исчезнувшего элемента, возникает исключение stale element reference exception. (stale - устаревший). Браузер сообщает, что элемента с таким id больше нет, он исчез.
Если искусственно создать такую ситуацию, например, вписать эту строчку:


Оно обновит страничку, айдишник у этого элемента будет другой. Локатор "q" будет тот же, а айдишник будет другим, это уже другой элемент.

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

Консоль разработчика, посмотреть код ошибки

Вкладка Network, там, где ошибочка, мы в левом блоке нажимаем на эту ошибочку. Справа открывается блок с несколькими вкладочками. Выбираем вкладку 'Response'.

Заметки по тестированию

В общем, ребята еще не допилили автозаполнение полей и дико бесит вбивать данные по сто раз на стринце чекаута.
Сережа тока что подсказал, как настроить автозаполнение в браузере.
В общем, зайти в настройки и в панельке поиска вбить address.
Потом найти там пункт "Autofill settings", там уже настроить автозаполнение полей)

 

воскресенье, 3 декабря 2017 г.

Запуск браузера, открытие страниц.

Во всех 5 поддерживаемых официально языках инициализация браузера выполняется путем конструирования объекта соответствующего класса.
Конструктор пытается найти исполняемый вспомогательный файл и запускает его, передавая туда какие-то опции.
В свою очередь этот вспомогательный исполняемый файл пытается найти браузер и запускает его.
Если какое-то действие фейл, значит из конструктора будут выключены исключения, драйвер не проинициализируется.
Траблы:
- браузер не запускается.
- вспомогательный файл не запускается.
Браузер забыть сложно, а вот вспомогательный файл очень даже легко, но С. выдает вполне внятную ошибку.
Вторая трабла - невозможность установить соединение между клиентской библиотекой и вспомогательным исполняемым файлом. Даже если он хорошо запустился, это не означает, что С. сможет с ним общаться. Т.к. общение происходит по сети, какие-нибудь настройки сетевого окружения или какая-нибудь программа прокси, файервол или антивирус может заблокировать сетевое окружение. В этом случае, конечно, сообщение об ошибке будет другим, типа, не удается установить соединение. Вспом. исп. файл запущен, но к браузеру не можем добраться, например, из-за траблов с сетевым подключением.
Если, например, впн, то часть трафика может идти как-то хитро, поэтому в каждом случае надо разбираться отдельно.

После запуска страниц откырвается специальная пустая страница и нам надо открыть страницу целевого приложения. driver.get or driver navigate to



Используем такой метод и в качестве параметра туда передается адрес, но полный, обязательно с "http://". Если в адресе не указан протокол, С. считает его невалидным.
Обычно это настраивается 1 раз. Типа, как юзер, открыл приложение, а дальше ходит по ссылкам.
Юзается, когда надо симитировать открытие ссылки, полученной, например, в скайпе или по электропочте.
+ используем тогда, когда надо оптимизировать переходы. Если для перехода из одного раздела целевого приложения в другое нужно нажать несколько кнопок в меню - это долго и сложно, можно вместо этого сразу перейти по нужному адресу. 


пятница, 1 декабря 2017 г.

Ключевые команды Selenium

Все начинается с запуска браузера.


(желтенькие - наиболее часто используемые)

Т.к. браузером управляет драйвер, значит мы инициализируем драйвер, а он запускает браузер.
 С. не может запуститься и управлять браузером, который уже работает. Он может управлять только тем драйвером, который сам запустил.
Все 5 официально поддерживаемых ЯП - ООП и инициализация драйвера выполняется путем создания объекта подходящего класса. Т.е. вызывается конструктор, который создает объект. И сразу же при вызове конструктора запускается вспомогательный исполняемый файл, который в свою очередь запускает браузер.

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

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

Дейсвтия с окнами. Специальные команды, которые позволяют открыть новое окно, в С. нет. Можно с помощью JS-кода, т.е. это делается при помощи совершенно другой команды, которая относится к другой группе.
С. умеет переключаться с одного окна на другое. И закрывать текущее окно. И если текущее окно было последним, значит браузер при этом тоже останавливается. Здесь тоже есть ловушки.

Действия с диалоговыми окнами. Это маленькие окошечки, в которых показывается кнопка "ОК" или кнопка "Cancel", а также там можно ввести какой-то текст. А еще диалоги, когда мы хотим загрузить файл на сервер или наоборот загрузить файл с сервера и сохранить его на локальный диск, ну, и другие виды диалога. С некоторыми С. умеет взаимодействовать, с некоторыми не умеет и их надо научиться избегать.

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

Но кроме этого человек совершает еще и какие-то действия. Выполняет клики мышкой и вводит какой-то текст с клавы. Это действия с элементами. Поддерживаются как простые действия, так и сложные (комбинации простых, например, клик мышкой, зажав клавишу Ctrl на клаве).

Иногда встречаются элементы. Это нечто среднее между обычным элементом и окном - фреймы, т.е. окна, вложенные внутрь страницы. С ними С. тоже работает.

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

четверг, 30 ноября 2017 г.

Общее описание инфраструктуры для работы с Селениумом

Для работы с Селениумом нужны:
- браузеры;
- дополнительный вспомогательный исполняемый файл (chromedriver, geckodriver, IEDriverServer);
- чтобы писать тесты на каком-либо ЯП, нужна клиентская библиотека, которая будет соединяться со вспомогательными исполняемыми файлами и через них управлять браузерами.



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

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


среда, 29 ноября 2017 г.

Инфраструктура для JavaScipt

IDEA (WebStorm).











Изначально язык JS использовался для того, чтобы писать какие-то скрипты внутри браузера. Ща это полноценный ЯП и программы могут запускаться вне браузера, как любые другие.
Когда мы пишем тесты или сценарии автоматизации для тестов, мы это так и делаем, отдельно, т.е. на уровне ОСи, чтобы управлять браузером.
Есть несколько различных реализаций интерпретатора JS. Здесь будем юзать NodeJS.
Дополнительные библиотеки обычно для него распространяются через сайт npmjs.com - это репозиторий, хранилище пакетов, а менеджер пакетов называется npm - node package manager.
Тестовый фреймворк - Mocha.
В общем, необходимо установить дополнения. Причем отдельно, которое поддерживает интерпретатор NodeJS и отдельно JS.
Специального типа модуля, который ориентирован на разработку тестов здесь нет, поэтому придется выбрать тип модуля, который подходит максимально, но не совсем точно, а потом выкинуть из него все лишнее.
Оставить только package.json  и подкаталог node_modules library tool, которая содержит установленные дополнительные библиотеки.
В клиентскую библиотеку селениума для JS уже включены примеры.



+ нужен исполняемый файл для того браузера, которым собираемся управлять. Они там лежат и могут быть найдены ОСью, когда надо.
Он сам не знает, что это тест, поэтому надо создать конфигурацию запуска, чтобы запускалось с mocha.
Надо выставить время, т.к. mocha используется в основном для разработки модульных тестов и там есть ограничение на время работы теста в 2 сек. Если модульный тест работает > 2 sec., это подозрительно. Но для тестов, которыми управляет реальный браузер, это слишком маленький таймаут, надо его увеличить.



пятница, 24 ноября 2017 г.

Заметки по работе с Селениумом

Если обращение к:
- css-селектору, пишем через точку: .form-field
- к тегу и атрибуту внутри него с каким-либо значением: input[type = "hidden"]
- к тегу и классу:  span.button__text

Все вместе вот так:


.getAttribute() тут тестик у Никиты был написан с обращением через xpath.

Ща пробану прописать через css-селектор.
Итак, переделываем.
Никитын варик был такой:

Я переделала и получилось отакэ:




четверг, 23 ноября 2017 г.

npm, selenium, linux, openvpn selenium-standalone

Кароч, ща для меня тут были магические действия. Шоб не потерять попробую как-то восстановить.
В общем, есть такой сайтец с npm. Я так поняла, здесь можно искать любые шняги нпмные.
Серега нашел здесь в поисковике 'selenium-standalone'. Там же был ман по его установке. Как я поняла, это пакет, который позволяет визуально увидеть шо происходит в браузере, когда мы запускаем тесты. Там прямо видно как оно прокликивается.
У меня перед этим не хотела эта шняга устанавливаться, ибо это Крым, детка, санкции.
Серега установил openvpn.
Про впн потом и ключи впн потом тады, ахха, если смогу восстановить хоть что-то.
Итак, после того, как Серега установил standalone, он перешел в папку с проектом. И, я так поняла, оно там запустило мои тесты и шо-та все вывалилось в консоль. Ну, результат прохождения тестов. Получилась откая шняга (Длинное, есичо, это та код картинки, который я просматриваю на этом сайте):


А вот с впн тоже ща пробану восстановить.
В общем, Серега скинул keys.tar.gz файлик с ключами vpn.
Мы его распаковали в домашней папочке. Я открыла, там всякие шняги, я так понимаю, страны, через которые можно заходить. На всякий пожарный заскриню:


Воот.

Потом он ввел вот такую команду, чтобы приконнектиться(?) ИМХО, ошибочно, ибо мы сам openvpn не установили еще на тот момент.
Вот скрин этой команды, нижняя строчка:


Потом мы установили: ХЗ, почему оно в папочке '~/open', которая синенькая. Так вот мы установили этот openvpn.



Потом снова, я так поняла, ввел чтобы приконнектиться такую команду:


Потом перешел в папочку с ключами:



Потом пробанул подконнектиться к Молдове:




Че-та не получилось и он снова пробанул через Германию, но уже Франкфурт:




Вроде заработало. Ну, а потом он стартанул Селениум-стендэлон:



И, как я понимаю, эти слэши между Страной и городом - это экранирование символов. В первом случае экранируется запятая, во втором случае экранируется пробел.
Хз, так ли оно, но, думаю, так, ибо файлик впновский выглядит вот так:



В общем, как-то так, угу.

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

Шоб оно выдавало скриншоты в таком, кодовом виде. Дописываем булеановскую (?) переменную и даем значение тру, ну, и каунтер ставим в 0. Я так поняла, чтобы потом оно нумеровало скриншоты.



Потом идем в то место, которое хотим заскриншотить, пишем там этот кусочек кода. Я хз шо оно там шо означает, но могу сделать предположение.

.screenshot() - я так понимаю, это мы обращаемся к переменной, которую создали там, в самом начале.
Потом
.then вызываем метод(?) - хз, не нашла его в WebdriverIO и пишем
.then(screen => {
  if(screenshot) {
    scrShotCount++;
    console.log('Screenshot' + scrShotCount + ': \n' + screen.value)
  }
})


Типа, перенаправляем поток (если встречаем нашу переменную скриншот, а еще делаем инкрементацию, шоб было видно, какой именно это скриншот по счету) в консоль.
console.log('Screenshot' + scrShotCount + ': \n' + screen.value) - отэта, я так понимаю, в скобочках, типа, как оно доложно отображаться на экранчике в консольке.
Шо-та вроде, типа, Скриншот1:, прыгаем на новую строку и выдаем его значение. А значение в закодированной картинке, хз, как оно там называется.
Угу, в консольке отакэ:




И берем потом эту длинную хрень, закодированную картинку, вставляем на этот сайт, шоб оно показало скрин.

среда, 15 ноября 2017 г.

DB, создание таблиц

Шоб создать таблицу, мы пишем команду
CREATE TABLE name_of_table
(
категория тип данных(количество символов),
категория тип данных(количество символов),
категория тип данных(количество символов),
категория тип данных(количество символов),
категория тип данных(количество символов),
);

вот скринчик с терминала:

понедельник, 13 ноября 2017 г.

Необходимость написать грамматику. DTD. XML

Мы почти никогда не будем с ним работать.
Смысл ДТД - прост. Это просто набор правил. Правил для кого? Для анализатора, объсняющих ему, в каком виде выглядит ваш документ.
Например, у нас есть документ:



У нас есть прайслист с элементом бук. Мне надо описать грамматику. В ДТД - это декларативная тема. Это набор инструкций, деклараций, правил, каждая начинается с восклицания "Пусть будет элемент букс!" Я объявляю элемент такой-то. В скобочках указываем их наполнение.

Пусть будет элемент прайслист, у него будет элемент букс, в котором будет тайтл, автор, прайс. Пусть будет элемент тайтл, а там #PCDATA (т.е. текст).


В ДТД много элементов, но нам ща нужны три:



ELEMENT - описывает тег, элемент.
ATTLIST - спиоск атрибутов (attribute list)
ENTITY - определяет сущность.

+, ? - модификаторы - они объясняют повторения этих элементов.

Скрин с примером ДТД:
У меня есть прайслист, в нем одна или более книг.  Если я хочу ноль или более - звездочка.
Элемент книга: в нем есть 1 тайтл по умолчанию, ноль или более авторов, одна цена и возможно есть, возможно нет, описание.
и т.д.

 А как сказать анализатору о том, что документ нужно проверять по этому описанию.
Есть 2 способа:
декларативно - в самом доке в XML ему указывается прямо в прологе  - восклицание
<!DOCTYPE - декларация, объяснение, объяснение нашей структуры.
А как для всего документа структуру описать, это же описание тега.
Что такое документ? Это корневой тег. Т.е. достаточно прописать структуру корневого тега - и мы описали весь документ.


В этом скирне первый блок - это все декларация. Т.е. декларирую прайслист. И дальше в квадратных скобочках указываю что может быть в прайслисте. Начинаю описывать ДТД самого прайслиста, доктайп, декларацию.
Т.о. мы анализатору объясняем что у нас должно быть в доке. Такой документ называется  самодостаточным - standalone.
В старых есть еще вверху такое: standalone="yes" - это кагбэ объясняет анализатору, что это самодостаточный документ, у него есть и ДТД, и сами данные.
Самодостаточными бывают редко, почти никогда, ибо много занимает 100-200 килобайт описания. Документ получается огромный, поэтому и юзают редко.
В html то же самое.
Т.о. у нас есть два способа указать документу ДТД:
1. Доктайп, имя корневого элемента, квадратные скобочки, а в них перечисление описания.
2. Мой-то стандарт никто не знает, поэтому паблик не юзаем никогда? - если парсер сам знает.
Пишем system, а затем указание на файл или урл.
Т.е. имеется books, описывается в файле books.dtd. Там может быть урл.
Вот два файлика, с описанием и сама books.dtd.




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

Когда открываем в эксплорере, на самом деле отрабатывает не эксплорер, а парсер msxml, входящий в состав ОС винда. У эсплорера xmlного парсера нет, он юзает стандартный виндовый парсер.
Здесь все зависит от самого парсера, от конкретного производителя.



Чаще всего так: стандартно парсеры при загрузке документа ничего не проверяют, чтобы сделать это как можно быстрее. Если речь идет о майкрософтовском парсере, у него есть специальное свойство, которое можно включить программно - валидэйтн парс. То же самое в пхп. Т.е. если оно программно включено до загрузки документа, то в этом случае он попытается проверить прямо на загрузке документа, но по умолчанию оно выключено.
У любого парсера есть специальная команда - проверяй. И вот тогда он уже пытается сделать соответствие между грамматикой и реальным документом. Браузер - это же не штука для работы c XML.
Это можно посмотреть в XML Tools. У браузера нет задачи проверки наших документов.
XML Tools - это инструмент для работы с XML. В т.ч. сюда входит свой парсер и у него есть команда 'validate now'.

DTD позволяет определить:
1. Какие теги допустимы.
2. Их повторение.
3. Их атрибуты.
4. Сущности.
ДТД - это грамматика.


















Атрибуты объявляются с помощью специального декларативного описания attlist - attribute list, т.е. список атрибутов. Он может объявить сразу несколько атрибутов.
Т.е. сначала название.
price - название элемента, для которого определяем атрибут.
currenty - атрибут.
CDATA - тип.
#REQUIRED - обязателен/необязателен.
хм... implied - необязателен, че-та не помню, шоб встречала это слово, забавно) А еще думаю, шо английский как-то знаю) Видимо, родственное implification, но там вроде совсем другой смысл.
В ДТД, когда мы объявляем содержимое элемента, мы всегда пишем PCDATA - парсируемые символьные данные. Т.е. анализатор обязан разбирать то, что находится внутри этих данных на наличие других элементов или сущностей. В других языках возможно - XJML - там допускались и другие элементы.
В атрибуте - CDATA, т.е. анализатор не должен разбирать то, что написано внутри атрибута.
Объявление ENTITY.





























Сущности XML

Мы сталкивались по HTML, что есть такой простой способ в XML описания т.н. спецсимволов. Когда я хочу написать, что а > b, в том же хтмл, мы говорили, что знак "больше" юзать нельзя, это зарезервированный символ и в HTML, и в XML. Обозначает он именно закрывание тега, а не больше.
В хтмл есть целый набор специальных знаков, который просто так на клаве не наберешь. Либо сложно, либо проще набрать по-другому.
Они записываются так:
&lt; - less then - меньше.
&gt - больше
&amp - амперсанд.
Эти три символа срабатывают в XML.
В хтмл таких сущностей много, например:
&nbsp; - неразрывный пробел, &copy - копирайт. В хтмл они определены, а в XML - нет. Это язык более абстрактный, универсальный.
Он ща рассматривается анализатором хтмла, т.е. их нет.
Мы уже объявили, что это типа хтмл, парсер это объявление увидел, он не знает, что в хтмл. Он не лазает вот сюда, вовнутрь. Необходимость объявления сущностей.



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

&lt; &gt, &amp - это константы, которые заменяют запрещенные символы. А для этих:  &nbsp; &copy - констант нет. Но XML - расширяем. Мы можем запилить что угодно. Например, компания, семейная компания.  Я в тексте пишу - вот сюда подставить название компании, оно раз - и подставило. Эти сущности могут быть не просто строками, они могут быть куском документа. В XML это все расширяемо. Где это описывается? В грамматике.

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