<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Alex Sergeev @ ALSEDI &#187; browser</title>
	<atom:link href="http://blog.alsedi.com/tag/browser/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.alsedi.com</link>
	<description>О QA, Shareware и ИТ</description>
	<lastBuildDate>Fri, 07 Oct 2011 08:52:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Совместимость сайтов с IE8</title>
		<link>http://blog.alsedi.com/sovmestimost-sajtov-s-ie8/</link>
		<comments>http://blog.alsedi.com/sovmestimost-sajtov-s-ie8/#comments</comments>
		<pubDate>Fri, 20 Mar 2009 15:36:46 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[browser]]></category>
		<category><![CDATA[ie8]]></category>
		<category><![CDATA[Internet Explorer]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[обновление]]></category>

		<guid isPermaLink="false">http://alsedi.com/blog/?p=368</guid>
		<description><![CDATA[Список возможных проблем и решений для них опубликован в блоге The Windows Internet Explorer Weblog. Основные вещи: - отключена возможность кросс-доменной и кросс-документной связей; - порядок атрибутов может отличаться от IE7, поэтому рекомендуется использовать обращение по имени - нельзя присвоить &#8230; <a href="http://blog.alsedi.com/sovmestimost-sajtov-s-ie8/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Список возможных проблем и решений для них опубликован в блоге <a href="http://blogs.msdn.com/ie/archive/2009/03/12/site-compatibility-and-ie8.aspx" target="_blank">The Windows Internet Explorer Weblog.</a> Основные вещи:</p>
<p>- отключена возможность кросс-доменной и кросс-документной связей;</p>
<p>- порядок атрибутов может отличаться от IE7, поэтому рекомендуется использовать обращение по имени</p>
<p>- нельзя присвоить неподдерживаемое значение в CSS</p>
<p>- GetElementById, теперь чувствителен к регистру букв (&#8220;Test&#8221; и &#8220;test&#8221; &#8211; для тего разные идентификаторы)</p>
<p>Дистрибутив: <a href="http://www.microsoft.com/rus/windows/internet-explorer/" target="_blank">http://www.microsoft.com/rus/windows/internet-explorer/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.alsedi.com/sovmestimost-sajtov-s-ie8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Приёмочное тестирование (Acceptance testing) web-приложений с PHP</title>
		<link>http://blog.alsedi.com/priyomochnoe-testirovanie-acceptance-testing-web-prilozhenij-s-php/</link>
		<comments>http://blog.alsedi.com/priyomochnoe-testirovanie-acceptance-testing-web-prilozhenij-s-php/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 21:04:45 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[acceptance testing]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[functional testing]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[phpunit]]></category>
		<category><![CDATA[selenium]]></category>
		<category><![CDATA[selenium core]]></category>
		<category><![CDATA[selenium rc]]></category>
		<category><![CDATA[unit testing]]></category>
		<category><![CDATA[браузер]]></category>

		<guid isPermaLink="false">http://alsedi.com/blog/?p=250</guid>
		<description><![CDATA[Перевод статьи padraic, с сайта ZEND Developer Zone. Статья была написана в середине 2007 года и некоторые ссылки на версии и пакеты могут быть не действительны. Примечания по поводу версий я добавлю прямо в тексте. Некоторые моменты в переводе были &#8230; <a href="http://blog.alsedi.com/priyomochnoe-testirovanie-acceptance-testing-web-prilozhenij-s-php/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Перевод статьи <a href="http://devzone.zend.com/member/2912-padraic" target="blank">padraic</a>, с сайта <a href="http://devzone.zend.com/article/2242-Acceptance-Testing-of-Web-Applications-with-PHP" target="blank">ZEND Developer Zone</a>. Статья была написана в середине 2007 года и некоторые ссылки на версии и пакеты могут быть не действительны. Примечания по поводу версий я добавлю прямо в тексте.</p>
<p>Некоторые моменты в переводе были для меня сложны и некоторые термины и определения переведены на русский дословно. При первом появлении для каждого специального термина в скобках приводится его английский источник. Например, для User Stories я предпочитаю использовать перевод «пользовательские истории», поскольку в большинстве случаев это подходит лучше, чем «пользовательские рассказы» или «идеи пользователя».</p>
<p>Так же в некоторых случаях, когда трудно подобрать синоним, либо одно слово объясняется предложением, используется принятый за стандартный жаргон, например: логин – как сущность, так и как действие.<br />
<span id="more-250"></span></p>
<h1>Приёмочное тестирование (Acceptance testing) web-приложений с PHP</h1>
<h2>Введение</h2>
<p>В этой статье я расскажу  о приёмочном тестировании (также известного как &#8211; функциональное тестирование), кое-что большинство PHP программистов смогут использовать в своей повседненвной практике. Я уверен, что многие из нас хорошо знакомы с юнит тестированием (unit testing), и даже интеграционным тестированием (Integration Testing), где же эта «лишняя спица в колесе» появляется при тестировании веб-приложений при нашей растущей одержимости Web 2.0 и AJAX, и как она отличается от первых двух методов? Ниже я объясню это. Также я покажу, как сделать приёмочное испытание с использованием убийственного сочетания PHPUnit и Selenium.</p>
<h2>Зачем нужны приёмочные испытания?</h2>
<p>Приёмочные испытания позволяют определить работает ли приложение так, как ожидает клиент (тот, кто заказал приложение). Теперь о том, что это означает&#8230;</p>
<p>Иногда трудно понять, как использовать приёмочные тесты при тестировании. Некоторые люди видят их подозрительно похожими (если не идентичными) на интеграционное тестирование. Интеграционное тестирование другой уровень процесса тестирования, отличный от юнит тестирования, которое проверяет, что компоненты приложения работают так, как ожидалось. Как и в случае с юнит тестами, это тестирование, как правило, занимается проверкой мест изолированных от остального кода с помощью MOCK объектов, заглушек и специальных тестовых классов.</p>
<p>Главное отличие приёмочных тестов в том, что они довольно просты. Интеграционные тесты работают по аналогии с юнит тестами, но с целыми группами связанных классов. Акцент делается на концепции «группы». Мы не тестируем каждый класс в отдельности, как с юнит тестами, а тестируем группы классов, которые вместе создают желаемый результат. Интеграционные тесты, поэтому написаны для и пишутся самими программистами. С другой стороны, приёмочные тесты работают для всего приложения (без изоляции классов и компонентов), как правило, по отношению к интерфейсу пользователя (<em>прим. в данном случае имеется ввиду не только графический интерфейс, но и любой другой реализованный в виде запросов и видимых ответов</em>), не важно для браузеров или веб-служб. Они пишутся для обеспечения соответствия приложения целям определенных клиентом. По сути, клиент даже может отвечать за написание тестов!</p>
<p>Теперь мы знаем, что приёмочное тестирование является самостоятельной практикой, но зачем нам её использовать?</p>
<ol>
<li> Она отражает ожидания клиента (а не для разработчиков!);</li>
<li>Она оценивает, когда функциональность значимая для клиента закончена (знание о том, когда нужно остановиться);</li>
<li>Она гарантирует быстрое определение будущего поведения, которое отличается от ожидаемого (регрессионное тестирование);</li>
<li>Как любой хороший набор тестов она поддерживает рефакторинг в том же порядке, как юнит и интеграционные тесты.</li>
</ol>
<h2>О пользовательских историях (User Stories) и приёмочных тестах</h2>
<p>Для тех, кто практикует экстремальное программирование, приёмочные тесты обычно пишутся для того, чтобы установить, что соответствие &#8220;пользовательским историям&#8221; является полным и не отклоняется от них в течение разработки.</p>
<p>Пользовательские истории &#8211; это краткое описание заказчиком некоторых частей значимой функциональности приложения, то есть ожидаемое поведение, которое должны проверять при приёмочных тестах. В плане XP (<em>eXtreme Programming</em>) это заменяет традиционную зависимость от спецификации, которая описывает каждый шаг в развитии, за счет жесткости в исполнении, с более гибким подходом, где наборы пользовательских историй отслеживают текущие требования. Пользовательские истории ведутся с пониманием положения, что план любого релиза, основанного на них, может подвергаться частым изменениям.</p>
<p>Давайте кратко посмотрим на написание пользовательских историй.</p>
<blockquote><p>Клиент может авторизоваться на сайте.</p></blockquote>
<p>Как PHP разработчики некоторые из нас могут посчитать это тупым и очевидным требованием. Старайтесь не думать так. Для клиента это важная функция. Если предположить, что дальнейшие обсуждения с клиентом не вызовут никаких изменений в этой пользовательской истории, то мы можем написать приёмочные тесты еще до начала разработки. Этот процесс звучит похоже на юнит тестирование &#8211; сначала тесты, потом код (<em>прим. На самом деле не совсем так и тут сказывается то, что автор больше работал в условиях XP или TDD, в условиях многомодульных проектов следование такому правилу себе дороже</em>). Вы можете оценить успешность реализации, независимо от того, все ли предварительно написанные тесты успешно пройдены (в нашем случае для веб-интерфейса). Дальше, после обсуждения идей с программистами клиент написал следующие тесты.</p>
<ol>
<li>Страница авторизации отображает форму для входа;</li>
<li>Отправка правильного сочетания идентификатора пользователя и пароля приводит к успешной авторизации;</li>
<li>Отправка недействительной пары логин – пароль, показать регистрационную форму с указанием ошибок;</li>
<li>Форма для логина всегда сопровождается гиперссылкой &#8220;Забыли логин или пароль?&#8221;.</li>
</ol>
<p>Неплохо выглядит, не так ли? Эта четверка тестов уже вторая пользовательская история, дополнительные ценные знания о важной функциональности для клиента.</p>
<blockquote><p>Клиент может восстановить забытый логин и пароль</p></blockquote>
<p>Если каждый из четырех тестов проходит, мы можем считать, что обе пользовательских истории реализованы. Кроме того, при приёмочных тестах это явный сигнал, что пора прекратить разработку для этой функциональности. Если только клиент не придёт с новыми идеями (или уточнением существующих) нет причин расходовать ресурсы на неё. Это сделано! Вперёд!</p>
<h2>Итерации</h2>
<p>В нашей команде, несущейся в авангарде экстремального программирования, мы также занимаемся привязыванием пользовательских историй к конкретным &#8220;Итерациям (Iterations)&#8221;. Итерация, в общем смысле, это определенный период разработки, к концу которого у нас должна быть полностью протестированная, рабочая (хотя и неполная) версия приложения, которая будет проходить все приёмочные тесты для всех пользовательских историй, привязанных к этой итерации. Я уверен, что многие из вас сталкивались с итерационной разработкой. Итерация, как правило, длится не более нескольких недель. Учитывая, что проект может длиться несколько месяцев в плане разработки будет множество итераций, и каждая новая планируется на основе предыдущей.<br />
Возвращаясь к нашему примеру. Пользовательская история про авторизацию была записана в итерацию # 1. Уверенный, что пришло время для разработки, вы загружаете ваш любимый редактор и принимаетесь за воплощение идеи. Следующий шаг? Написать приёмочные тесты в виде автоматизированного тестирования там, где это возможно.</p>
<h2>Подготовка к приёмочному тестированию</h2>
<p>Требования:</p>
<ul>
<li>PHPUnit 3.0 <a href="http://www.phpunit.de">http://www.phpunit.de</a></li>
<li>Testing_Selenium<a href="http://pear.php.net/"> http://pear.php.net/</a></li>
<li>Java 5 (1.5.0) требуется для Selenium RC <a href="http://java.sun.com">http://java.sun.com</a></li>
<li>Selenium Remote Control (RC) <a href="http://openqa.org/">http://openqa.org/</a></li>
</ul>
<p>Многие PHP программисты стремятся использовать PHP библиотеки для написания приёмочных тестов, и это подход я использую здесь. В этой статье мы будем использовать PHPUnit, который с версии 3.0 содержит класс <strong>PHPUnit_Extensions_SeleniumTestCase</strong>, который может быть использован для определения приёмочных тестов и используется с Selenium Core при тестировании. Важно отметить, что эти тесты не являются юнит тестами. Да, PHPUnit это библиотеки для юнит тестирования, но они столь же эффективны для интеграционных и приёмочных тестов.</p>
<p>Руководство по использованию PHPUnit с Selenium можно почитать тут:  <a href="http://www.phpunit.de/pocket_guide/3.1/en/selenium.html">http://www.phpunit.de/pocket_guide/3.1/en/selenium.html</a>. Расширение PHPUnit для Selenium также потребует, установленного пакета PEAR Testing_Selenium. PHPUnit и Testing_Selenium могут быть взяты из PEAR (PHPUnit 3 доступен только через phpunit.de, руководство по установке тут <a href="http://www.phpunit.de/pocket_guide/3.1/">http://www.phpunit.de/pocket_guide/3.1/</a>).</p>
<p>Selenium это веб-приложение для приёмочного тестирования (	<em>прим. не совсем верно. Selenium это всё-таки функциональное тестирование, но может быть использован и для приёмочного</em>) веб-приложений, созданное ThoughtWorks. В него входит несколько пакетов приложений, включая Selenium Core, Selenium RC и Selenium IDE. Его цель состоит в том, чтобы запустить тесты в реальном браузере (со всеми тараканами и примочками!), используя Selenium Core для воспроизведения действия пользователя, их проверки и создания отчетов с результатами тестирования. Selenium Core написан на Javascript и содержит в себе &#8220;BrowserBot&#8221;. Selenium Remote Control &#8211; это дополнительный сервер, который потребуется для запуска тестов приведенных в этой статье. Он позволяет использовать любой язык программирования для взаимодействия с Selenium Core в браузере через посылку простых HTTP GET запросов на сервер RC. Все это звучит сложно, но работать с ним просто.</p>
<p>Обратите внимание, что прошло много времени с момента последнего релиза Selenium RC 0.9.0 (привет 2006 году),в этой статье я рекомендую использовать снапшот Selenium 0.9.2. Это необходимо, поскольку версия 0.9.0 не очень хорошо работает с последними версиями Firefox 2 и Internet Explorer 7 (<em>прим. последние релизы Selenium RC и Core были сделаны в январе 2009 (буквально вчера), поэтому плясать с бубном не нужно, но нет гарантий, что тесты из этой статьи заработают</em>). Из архива Selenium RC потребуется только один JAR файл с названием &#8220;selenium-server-standalone.jar&#8221;.</p>
<p>Базовая форма приёмочных тестов с применением PHPUnit и Selenium RC очень проста.</p>
<p><code>/** PHPUnit_Extensions_SeleniumTestCase */<br />
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';</code></p>
<p>class GoogleIndexTest extends PHPUnit_Extensions_SeleniumTestCase<br />
{<br />
protected function setUp()<br />
{<br />
/**<br />
* &#8216;*firefox&#8217; =&gt; Firefox 1 or 2<br />
* &#8216;*iexplore&#8217; =&gt; Internet Explorer (all)<br />
* &#8216;*custom /path/to/browser/binary =&gt; Любые другие браузеры (включая Firefox в Linux)<br />
* &#8216;*iehta&#8217; =&gt; экспериментальный встроенный IE<br />
* &#8216;*chrome&#8217; =&gt; Экспериментальный профайл для Firefox (не браузер Chrome)<br />
*/<br />
$this-&gt;setBrowser(&#8216;*firefox&#8217;);<br />
$this-&gt;setBrowserUrl(&#8216;http://www.google.ie/&#8217;); // сайт, который будем тестировать<br />
}</p>
<p>public function testTitle()<br />
{<br />
$this-&gt;open(&#8216;http://www.google.ie/&#8217;); // открыть дефолтную страницу<br />
$this-&gt;assertTitleEquals(&#8216;Google&#8217;); // проверить существует ли ожидаемый заголовок (title).<br />
}<br />
}</p>
<p>Метод SetUp ()используется для определения наших тестов, начнём тут с указания какой браузер использовать. Firefox – один из возможных вариантов. Если Selenium RC не содержит ссылка на ваш браузер вы можете использовать префикс &#8220;*custom&#8221; и путь до браузера. Функция setBrowserUrl () устанавливает основной URL для тестов. Обычно это главная (начальная) страница вашего приложения (например, index.php). Страница доступна для тестов, только когда она открыта (если это не очевидно). Поэтому тесты лучше начинать с открытия страницы с помощью функции open().</p>
<p>Selenium Core (Javascript BrowserBot) работает в окне браузера, что происходит достаточно просто понять после небольшой практики. Существует пять концепций, которые необходимо понять с самого начала:</p>
<ol>
<li>Действия (Actions, Selenium Actions)</li>
<li> Accessors</li>
<li> Assertions</li>
<li> Локатор элементов (Element Locators)</li>
<li> Шаблоны (Patterns)</li>
</ol>
<p>Действия просто все ожидаемые действия, которые могут манипулировать состоянием веб интерфейса. Действия включают в себя нажатие на ссылку, нажатие клавиш, позиционирование мыши (например, onmouseover) и так далее. Все, что пользователь может сделать, Selenium Actions могут сделать тоже. Многим действия может быть указано ожидать определенного состояния. Самым простым является суффикс &#8220;AndWait&#8221;, который можно прикрепить к действиям, например, clickAndWait(). Это указывает Selenium, что после нужно отправить запрос на веб сервер и дождаться ответа перед тем как продолжить. Из-за изворотливого характера Selenium RC я рекомендую вам избегать использования &#8220;WaitFor&#8221; (ужасно работает в версии 0.9 и снапшоте 0.9.2 (прим. в 1.0 вроде ничего так)) и использовать отдельный вызов &#8220;waitForPageToLoad()&#8221;, &#8211; мы рассмотрим это действие позже.</p>
<p>Accessors – отслеживание состояния. Они могут быть использованы для хранения значений в переменных для последующего использования или сравнения. Использование accessors может быть весьма полезно во многих случаях, но тут мы о них только упомянем.</p>
<p>Assertions так же, как и Accessors оценивают состояние. Но они также позволяют сравнить хранимое значение с ожидаемым. Есть два основных типа &#8220;assert (прим. упрощая – это жесткое сравнение – хоть тресни, а должно быть)&#8221; и &#8220;verify (проверить)&#8221;. В Selenium Core неравенство при assert приведет к окончанию теста, в то время как неравенство при сравнении приведет только к записи в лог.<br />
Чтобы получить информативный результат теста, попробуйте использовать методы assert только при крайней необходимости, где неравенство или несоответствие делает продолжение теста бессмысленным.</p>
<p>NB: При тестировании AJAX веб-интерфейсов &#8220;WaitFor&#8221; методы чрезвычайно удобны для определения того, когда AJAX манипулирует с DOM, после чего вы можете использовать обычные verify / assert. Лучше всего в таких случаях функция waitForCondition(), которая использует Javascript выражения, делающие проверки, в цикле или в течение определенного времени.</p>
<p>Полный список возможных действий, Accessors и Assertions существующих в Selenium Core тут:  <a href="http://www.openqa.org/selenium-core/reference.html">http://www.openqa.org/selenium-core/reference.html</a>. Список большой, так что при тестировании можно долго развлекаться.</p>
<p>Два последних понятия это локатор элементов и шаблоны. Локатор – это метода для поиска элементов HTML/XML для тестирования. Selenium Core поддерживает поиск с помощью идентификатора и имени элемента, выражений Javascript DOM, XPath, CSS селекторов, и текста ссылки.</p>
<p>Шаблоны это методы для определения текста для поиска. По умолчанию используется метод &#8220;glob&#8221; (например, «*»/«?»). Также можно использовать точный поиск (полное совпадение). Ну, и где бы мы были без &#8220;регулярного выражения&#8221;! Несколько примеров я приведу позже.</p>
<h2>Реализация пользовательских историй (или &#8211; вот одна из подготовленных ранее)</h2>
<p>Чтобы не уходить в сторону от темы, будем считать, что пользовательские истории уже реализованы в коде. Необходимо скачать и установить локальную копию. Код написан с использованием Zend Framework), и уже протестирован с PHPUnit и Slenium.<br />
<a href="http://downloads.astrumfutura.org/devzone/Acceptance_Testing_Tutorial_Application.tar.bz2">http://downloads.astrumfutura.org/devzone/Acceptance_Testing_Tutorial_Application.tar.bz2</a> (<em>прим. файл доступен</em>)</p>
<p>Для установки, просто импортируйте /INSTALL.sql в базу данных, скопируйте файл <strong>/src/config/config.ini.dist</strong> в <strong>/src/config.ini</strong> и поменяйте настройки под ваше окружение, тоже самое сделайте для <strong>/tests/TestConfiguration.php</strong>. В этом конфигурационном файле, вы можете изменить значение TESTS_SELENIUM_BROWSER на любой другой вариант (список выше в примере). Baseurl также должен быть изменен и указывать на наше приложение в /WWW каталоге.</p>
<p>Что еще? Предположим, что установка была в корень сайте: зайдите на http://localhost/www/. Вы можете запустить все тесты, которые мы напишем ниже, они расположены тут: http://localhost/tests/AllTests.php</p>
<h2>Написание  и проведение приёмочных испытаний</h2>
<p>Приступим к делу. Я уверен, что достаточно теории на этот момент! Итак, какой был первый приёмочный тест поставленный клиентом?</p>
<h3>1. Страница авторизации отображает форму для входа</h3>
<p>Наша форма для авторизации находится по адресу “/login” главного файла приложения. Это тот самый URL который нужно открыть в Selenium Core. Во-вторых, наш тест должен проверять наличие регистрационной формы на странице. Мы уже (см. <strong>/src/default/views/scripts/login_index.phtml</strong>) обозначили форму для входа, и установили уникальный идентификатор &#8220;login-form&#8221;, по которому мы можем её найти. Также мы уже знаем (из того же шаблона), что должны существовать два поля с идентификаторами &#8220;identity&#8221; и &#8220;password&#8221;. Для расширения кругозора мы будем использовать разные шаблоны в локаторе элементов</p>
<p><code>/** PHPUnit_Extensions_SeleniumTestCase */<br />
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';</code></p>
<p>class LoginIndexTest extends PHPUnit_Extensions_SeleniumTestCase<br />
{<br />
protected function setUp()<br />
{<br />
$this-&gt;setBrowser(&#8216;*firefox&#8217;); // или *iexplore для IE<br />
$this-&gt;setBrowserUrl(&#8216;http://localhost/&#8217;);<br />
}</p>
<p>public function testLoginFormExists()<br />
{<br />
$this-&gt;open(&#8216;http://localhost/login&#8217;);</p>
<p>$this-&gt;assertElementPresent(&#8220;id=login-form&#8221;);<br />
$this-&gt;assertElementPresent(&#8220;dom=document.forms['login-form'].identity&#8221;);<br />
$this-&gt;assertElementPresent(&#8220;dom=document.forms['login-form'].password&#8221;);<br />
$this-&gt;assertElementPresent(&#8220;xpath=//form[@id='login-form']/input[@type='submit']&#8220;);<br />
}<br />
}</p>
<p>Если вы скачали готовое приложение, то уже, вероятно запускали этот тест. Полный тест файл находится в файле /tests/AcceptanceTests/UserLoginTest.php. Возможно, вы уже догадываетесь, что добавление браузера и URL напрямую в код приведет к постоянным изменениям – поэтому в этих тестах используется набор констант из файла /tests/TestConfiguration.php.dist.</p>
<p>В примере выше встречается функция assertElementPresent(). Это проверка на наличие определенных элементов HTML / XML. Аргументом является строка, где тип локатора указывается слева от знака равно, а аргумент справа. Я использовал три различных типа. ID проверяет существование  элемента с ID равным &#8220;login-form&#8221;. Наличие двух полей ввода проверяется с помощью выражений Javascript DOM. Наличие кнопки проверяется с помощью XPath.</p>
<p>Достаточно ли этих тестов? Существует риск, что если мы будем делать тесты слишком конкретизированными, то потом потребуется много времени на их редактирование при изменении интерфейса. Тем не менее, кое что еще должно быть проверено. Например, совпадает ли максимальная длина поля (maxlength) с длиной поля VARCHAR в базе данных или превышает его?</p>
<p><code>$this-&gt;assertElementPresent("xpath=//input[@id='identity' and @maxlength='20']");<br />
$this-&gt;assertElementPresent("xpath=//input[@id='password' and @maxlength='64']");<br />
</code></p>
<h3>2. Отправка правильного сочетания идентификатора пользователя и пароля приводит к успешной авторизации.</h3>
<p>Теперь мы добавим тест, который будет отправлять валидные данные пользователя и проверять появилось ли сообщение, определенное в темплейте (см. темлейт login_index.phtml)<br />
<code><br />
public function testValidAuthentication()<br />
{<br />
$this-&gt;open('http://localhost/login');</code></p>
<p>// заполняем форму<br />
$this-&gt;type(&#8220;dom=document.forms['login-form'].identity&#8221;, &#8216;Padraic&#8217;);<br />
$this-&gt;type(&#8220;dom=document.forms['login-form'].password&#8221;, &#8216;KSkjduj$!hjj*927&#8242;);</p>
<p>// отправляем данные<br />
$this-&gt;click(&#8220;xpath=//form[@id='login-form']/input[@type='submit']&#8220;);<br />
$this-&gt;waitForPageToLoad(30000); // 30 секунд по умолчанию</p>
<p>// проверяем сообщение<br />
$this-&gt;assertTextPresent(&#8216;exact:Welcome, Padraic&#8217;);</p>
<p>// проверяем, что нет сообщений об ошибке<br />
$this-&gt;assertTextNotPresent(&#8216;*invalid*&#8217;);<br />
}</p>
<p>В примере виден ряд новых действий (action) и assertion методов. Первый type().type() имитирует ввод данные пользователем в текстовое поле, и мы используем его здесь, чтобы Selenium Core заполнил регистрационную форму. Действие click() определяет элемент для которого Selenium Core смоделирует нажатие (есть также метод submit() который можно использовать вместо click()). Дополнительный метод waitForPageToLoad() указывает Selenium, что после запроса будет ответ с сервера, и он должен ждать ответа перед тем, как продолжить. Оба PHPUnit и Selenium поддерживают метод clickAndWait(), который объединяет методы click() и waitForPageToLoad(). На момент написания статьи этот метод не работал, видимо будет в «следующем релизе», ну что же подождем и посмотрим…</p>
<p>Также в примере представлены методы assertTextPresent() и assertTextNotPresent(). Оба метода содержат шаблоны. Если вы вспомните, шаблоны используются для поиска текста на странице, используя различные методы, включая поиск glod, регулярные выражения и точное соответствие. В примере используется точное соответствие. Если вы не определите тип шаблона, по умолчанию будет использован &#8220;glob&#8221;. Хотя это и не плохо, вы, возможно, промахнетесь при поиске строк, которые содержат элементы glob &#8211; звездочка или знак вопроса.</p>
<h3>3. Она гарантирует быстрое определение будущего поведения, которое отличается от ожидаемого (регрессионное тестирование)</h3>
<p><code><br />
public function testInvalidAuthenticationWithError()<br />
{<br />
$this-&gt;open('http://localhost/login');</code></p>
<p>// заполняем<br />
$this-&gt;type(&#8220;dom=document.forms['login-form'].identity&#8221;, &#8216;Maugrim&#8217;);<br />
$this-&gt;type(&#8220;dom=document.forms['login-form'].password&#8221;, &#8216;badpass&#8217;);</p>
<p>// отсылаем<br />
$this-&gt;click(&#8220;xpath=//form[@id='login-form']/input[@type='submit']&#8220;);<br />
$this-&gt;waitForPageToLoad(30000); // 30 secs</p>
<p>// проверяем, что логин не прошел<br />
$this-&gt;assertTextNotPresent(&#8216;regexp=Welcome,[a-zA-Z0-9 -_aouieAOUIE]&#8216;);</p>
<p>// проверяем, что ошибка появилась на странице<br />
$this-&gt;assertTextPresent(&#8216;*invalid*&#8217;);<br />
}</p>
<p>Ничего нового здесь не появилось, за исключением использования регулярного выражения поскольку текст ошибки может содержать любое валидное имя пользователя. Поэтому мы подходим широко и отсекаем любые правильные логины. Это будет означать, что регулярное выражение соответствует насколько это возможно (или чуть шире) логике в нашем приложении.<br />
И наконец, четвертый тест!</p>
<h3>4. Форма для логина всегда сопровождается гиперссылкой &#8220;Забыли логин или пароль?&#8221;.</h3>
<p>Это больше изменение теста testLoginFormExists, чем новый тест. Мы просто добавим следующее:<br />
[code]<br />
public function testLoginFormExists()<br />
{<br />
//  ...</p>
<p>// проверяем существует ли ссылка<br />
$this-&gt;assertElementPresent('link=regexp:^Forgot identity or password?$');<br />
}<br />
[/code]</p>
<p>Когда мы соберем этим тесты вместе, мы, наконец, получи приёмочные тесты достаточные, чтобы сказать, что пользовательская история была реализована и работает. Это, скорее всего, минимальный тесты, так как мы не включили тесты, ориентированные на разработчиков, таких как проверка maxlength, чтобы они соответствовали нашей базе данных, но пока этого достаточно.</p>
<h2>Как запускать тесты?</h2>
<h3>1. Запуск сервера Selenium RC</h3>
<p><code>java -jar selenium-server-standalone.jar</code></p>
<p>Перед запуском нужно убедиться, что пути до выбранного браузера и Java добавлены в переменную PATH.</p>
<h3>2. Запустите файл AllTests.php из каталога /test в браузере.</h3>
<p>Если все пойдет хорошо, вы увидите, как трижды браузер открылся и закрылся (можно использовать опцию прокси в Selenium RC, чтобы использовать один и тот же браузер), и результаты будут показаны в браузере.</p>
<h2>Заключение</h2>
<p>Приёмочное тестирование – это ценная обучающая практика. При оценке как приложение работает против набора тестовых ожиданий мы можем оценить завершенность продукта в целом и попадание в сроки разработки. При отсутствии приёмочного тестирования у нас нет уверенности, и придется тратить больше времени на ручное тестирование приложений. Ручное тестирования требует гораздо больше времени, и оно в меньшей степени, охватывает все потенциальные проблемы. Кроме того, интеграционные и юнит тесты не являются заменой приёмочным. Приёмочные тесты – это просто, и требуют совсем немного практики, чтобы начать работу. Я надеюсь, что эта статья поможет вам на этом поприще!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.alsedi.com/priyomochnoe-testirovanie-acceptance-testing-web-prilozhenij-s-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Browser Security Handbook</title>
		<link>http://blog.alsedi.com/browser-security-handbook/</link>
		<comments>http://blog.alsedi.com/browser-security-handbook/#comments</comments>
		<pubDate>Thu, 18 Dec 2008 13:40:06 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[browser]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[безопасность]]></category>
		<category><![CDATA[браузер]]></category>
		<category><![CDATA[документация]]></category>
		<category><![CDATA[книга]]></category>

		<guid isPermaLink="false">http://alsedi.com/blog/?p=198</guid>
		<description><![CDATA[На Google Code обновилась книга о безопасности браузеров &#8211; Browser Security Handbook, которая весьма полезна для разработчиков, как-либо связанных с Web. This document is meant to provide web application developers, browser engineers, and information security researchers with a one-stop reference &#8230; <a href="http://blog.alsedi.com/browser-security-handbook/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>На <a href="http://code.google.com">Google Code</a> обновилась книга о безопасности браузеров &#8211; <a href="http://code.google.com/p/browsersec/wiki/Main">Browser Security Handbook</a>, которая весьма полезна для разработчиков, как-либо связанных с Web.</p>
<blockquote><p>This document is meant to provide web application developers, browser engineers, and information security researchers with a one-stop reference to key security properties of contemporary web browsers. Insufficient understanding of these often poorly-documented characteristics is a major contributing factor to the prevalence of several classes of security vulnerabilities. </p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.alsedi.com/browser-security-handbook/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Chrome преподносит сюрпризы</title>
		<link>http://blog.alsedi.com/google-chrome-pripodnosit-syurprizy/</link>
		<comments>http://blog.alsedi.com/google-chrome-pripodnosit-syurprizy/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 11:35:42 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[browser]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[браузер]]></category>
		<category><![CDATA[нарушение безопасности]]></category>
		<category><![CDATA[программы]]></category>

		<guid isPermaLink="false">http://alsedi.com/blog/?p=147</guid>
		<description><![CDATA[Вышла новая версия Google Chrome 0.4.154.18, пока только для Dev Channel, то есть неофициально. Последняя публичная версия &#8211; 0.3.154.9. Сюрприз же прятался в хитром механизме автоматического обновления. Во-первых обновления закачивают без спроса. Я ставил версию 0.2 и про то, что &#8230; <a href="http://blog.alsedi.com/google-chrome-pripodnosit-syurprizy/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://googlechromereleases.blogspot.com/2008/11/dev-release-0415418.html" target="_blank">Вышла новая версия Google Chrome 0.4.154.18</a>, пока только для Dev Channel, то есть неофициально. Последняя публичная версия &#8211; 0.3.154.9.</p>
<p>Сюрприз же прятался в хитром механизме автоматического обновления. Во-первых обновления закачивают без спроса. Я ставил версию 0.2 и про то, что у меня стоит более свежая версия узнал только когда посмотрел About. Но я не скачивал третью версию и не давал разрешения на обновление&#8230; Во-вторых автоматический апдейт отключить не получится &#8211; такой опции в настройках нет вообще.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.alsedi.com/google-chrome-pripodnosit-syurprizy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Часть 1: Google Chrome</title>
		<link>http://blog.alsedi.com/chast1-google-chrome/</link>
		<comments>http://blog.alsedi.com/chast1-google-chrome/#comments</comments>
		<pubDate>Wed, 10 Sep 2008 09:38:23 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[browser]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[браузер]]></category>

		<guid isPermaLink="false">http://alsedi.com/blog/chast1-google-chrome/</guid>
		<description><![CDATA[Часть 2: Google Chrome для разработчиков Вышедший второго сентября Google Chrome успел наделать много шума и стал довольно обсуждаемой темой в блогосфере. Не меньший интерес проявили и специалисты по безопасности, в первой же версии был обнаружен ряд уязвимостей. Первая из &#8230; <a href="http://blog.alsedi.com/chast1-google-chrome/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p align="left"><a href="http://alsedi.com/blog/chast-2-google-chrome-dlya-razrabotchikov/">Часть 2: Google Chrome для разработчиков</a></p>
<p align="left">Вышедший второго сентября <a href="http://www.google.com/chrome" target="blank">Google Chrome</a> успел наделать много шума и стал довольно обсуждаемой темой в блогосфере. Не меньший интерес проявили и специалисты по безопасности, в первой же версии был обнаружен ряд уязвимостей. Первая из них была обнаружена уже на следующий день.  Чуть менее недели спустя Google выпустил патч для найденных критических проблем.  За очень короткое время после релиза браузер отвоевал маленькую, но заметную долю рынка.</p>
<p align="left">Все эти события прошли мимо меня, пока я был в отпуске. Ну и ладушки.</p>
<p align="left">Поскольку появление нового инструмента в руках пользователей всегда влечет определенные проблемы для тестирования, браузер пришлось отыскать и установить. Сейчас он (официальный сайт Google Chrome) занимает третью позицию в Google (PR 0), вторую в Yahoo, третью MSN, видимо дальние позиции в Live Search и Yandex, первую в <a href="http://www.majestic12.co.uk/" target="blank">Majestic 12</a>, а Alexa почему то найти не удалось. Хорошие показатели, на мой взгляд после восьми дней жизни.</p>
<p align="left">Инсталятор, скачиваемый на компьютер, меньше полумегабайта. Правда, при установки он скачивает из Сети порядка 20 Мегабайт данных.  Устанавливается не в привычные “Program Files”, а в “Documents and Settings”. Прямо скажем очень странное решение. Занимает после установки около пятидесяти мегабайт, при этом сам инсталлятор не удаляется и лежит в папке “[Version]\Installer”. Вероятно, установка следующих версий будет приводить к накоплению данных.</p>
<p align="left">Судя по структуре файлов, дальше планируется появление плагинов и тем. Смущает только реализация в виде DLL.</p>
<p align="left">Первым не очень понятным фактом стало то, что запущенный Chrome загружает процессор от 2 до 7% постоянно. Такого поведения не наблюдается у Internet Explorer, Firefox и Opera. Простая загрузка браузера с пустой страницей не приводит к постоянной нагрузке на процессор. Что же делает при этом Chrome? При беглом осмотре понятно не стало – к файлам обращается в меру, при этом в своей директории, реестр использует не больше остальных, в Сеть тоже постоянно не ломится. Исходный код скачивать поленился, возможно, позже всё же пересилю себя.</p>
<h2>Интерфейс и функциональность.</h2>
<p align="left">Стандартный интерфейс, как и у других браузеров, только сильно урезанный или без лишних элементов, смотря с какой точки зрения подходить. Если браузер воспринимать именно как инструмент для простого просмотра страниц, то очень хорошо. У меня же вызвало смешанные чувства. Такого же эффекта можно добиться в Firefox, IE и Opera нажав F11, разница лишь в том, что при этом браузеры основной тройки разворачиваются на весь экран.</p>
<p><a href="http://alsedi.com/blog/wp-content/upload/menu-bar.png" target="blank"><img src="http://alsedi.com/blog/wp-content/upload/menu-bar-th.png" border="0" alt="" width="400" height="156" /></a></p>
<p><a href="http://alsedi.com/blog/wp-content/upload/menu-bar.png" target="blank"><br />
Click!</a></p>
<p>Куда интереснее поведение адресной строки при вводе ссылки.<br />
<a href="http://alsedi.com/blog/wp-content/upload/type-url.png" target="blank"><img src="http://alsedi.com/blog/wp-content/upload/type-url-th.png" border="0" alt="" /></a><a href="http://alsedi.com/blog/wp-content/upload/type-url.png" target="blank"><br />
Click!</a></p>
<p align="left">Во-первых шрифт и поле ввода больше, чем у других браузеров. Во вторых цветами отделается домен, символы разметки, пути до страницы на сайте и имена файлов. Немного необычно, но приятно. При вводе адреса Chrome показывается в выпадающем списке возможные результаты, основанные на уже существующей истории пользователя и наиболее близких имен доменов в базе Google. Так же предлагается поискать введенную фразу в выбранном поисковике (по умолчанию Google) и посмотреть всю историю по страницам, попадающую под введенное в адресную строку. Пожалуй, этим можно было удивить в прошлом году, пока не вышел браузер Firefox 3.0. Но всё-таки хорошо, что такая возможность есть уже в первых версиях, потому как ни IE, ни Opera этого пока не сделали (поиск идет по локальной истории).В новом пустом табе (по Ctrl + T например) по умолчанию отображаются наиболее часто посещаемые сайты, а так же список недавних закладок.</p>
<p align="left">Порадовал и поиск по истории браузера. Вообще функциональность очень мне понравилась, в FF и Opera существует похожая возможность, но реализована она по другому – все ячейки пользователь заполняет самостоятельно.</p>
<p align="left">Совсем другой разговор, если обратить внимание на табы. Все стандартные действия поддерживаются (переключение по Ctrl + цифра, Shift, Ctrl, Shift &amp; Ctrl + Click), табы можно менять местами, а так же вообще вытаскивать их в отдельное окно и вкладывать отдельные окна друг в друга. Анимация табулек при перетаскивании и вложении сделана приятно.</p>
<p align="left">При этом, как обещает Google, зависание одного таба не скажется на остальных. Подвесить Chrome удалось легко. Было достаточно загрузить небольшой PDF документ. Пока он полностью не загрузился окно Chrome зависло и переключится на другие табы и отдельные окна не получалось.  Другие приложения работали нормально. Так получается из-за того, что на самом то деле табы не являются самостоятельными процессами и запускаются от процесса ядра (это видно через Process Explorer). В результате, когда повисает главный процесс &#8211; повисает и всё остальное. Но с другой стороны, если правильно угадать, то можно убить дочерний процесс, подвесивший всё приложение, тогда действительно на других табах это не скажется. У Internet Explorer таже история, если открывать страницы не в табах, а в отдельных окнах.</p>
<p><img src="http://alsedi.com/blog/wp-content/upload/host-process.png" border="0" alt="" /></p>
<p align="left">Другая возможность &#8211; создание ярлыков. Любая страничка может быть помещена на рабочий стол, в меню «Пуск» или на панель быстрого запуска.  В отличии от простого drug-and-drop для других браузеров, в Chrome существует дополнительный пункт меню который позволяет создать сразу все ярлыки. При этом иконка берется из favicon.ico сайта.</p>
<p><a href="http://alsedi.com/blog/wp-content/upload/shortcut-create.png" target="blank"><img src="http://alsedi.com/blog/wp-content/upload/shortcut-create-th.png" border="0" alt="" /></a><a href="http://alsedi.com/blog/wp-content/upload/shortcut-create.png" target="blank"><br />
Click!</a></p>
<p align="left">Запускаются такие ярлыки в отдельном окне Chrome, вообще без навигации. Впрочем, с помощью меню в заголовке окна можно переключиться в нормальный режим. Чем то напоминает Active Desktop, только окна нормальные, а не «утопленные» на заднем плане.Любопытно сделан контекстный поиск по странице. По «Ctrl + F» панелька для ввода появляется чуть ниже строки адреса. При вводе текста показывается количество соответствий и текущее положение.</p>
<p align="left">История посещений и загрузок показываются в отдельном окне в виде веб страниц, с возможностью поиска. Лично мне понравилось, потому как довольно удобно использовать. К сожалению, интерактивного поиска нет (как в Firefox в истории посещений). Функция удобная, когда нет уверенности в точном названии страницы.Интересно еще и то, что иногда количество процессов было больше чем процесс ядра + количество открытых табов и окон Chrome.Я заметил еще одну приятную особенность. При открытии новых окон, они появляются не как обычно правее и ниже родительского, а чуть ниже верхней грани, по середине заголовка.</p>
<p><a href="http://alsedi.com/blog/wp-content/upload/new-windows.png" target="blank"><img src="http://alsedi.com/blog/wp-content/upload/new-windows-th.png" border="0" alt="" /></a><a href="http://alsedi.com/blog/wp-content/upload/new-windows.png" target="blank">Click!</a></p>
<p align="left">Ребята из Google добавили любопытную функцию в браузер – диспетчер задач. Вызвать диспетчер можно из контекстного меню заголовка браузера.</p>
<p><img src="http://alsedi.com/blog/wp-content/upload/task-manager.png" border="0" alt="" /></p>
<h2>Производительность и стандарты.</h2>
<p align="left">Чисто субъективно я не заметил никакой разницы между браузерами в плане скорости загрузки страниц. Страницы с видео роликами, так или иначе, подтормаживаются при загрузке. Не было чудес и при загрузке «Google Analytics» &#8211; так же заметны подтормаживания при смене периода.Очень хорошо почувствовал разницу в скорости обработки страницы при изменении размеров текста с помощью «Ctrl + Колёсико Мышки» и Ctrl + «+/- ».  Chrome работает очень быстро, практически без задержек. Но, в Chrome возможность увеличения и уменьшения текста ограничена, в отличие от Firefox. Вместе с тем, на мой взгляд, увеличение лучше работает в Internet Explorer и Opera – не портит разметку, и при этом позволяет увеличить страницу, так что на картинках будут видны пикселы.</p>
<p align="left">При старте Chrome в пике съедал 40% процессора (у меня стоит AMD Athlon 3500+ 64 bit с 1 GB Dual памяти и водруженной поверх XP 32 bit с SP3).  Для сравнения Firefox потреблял 35%, Internet Explorer -60%, Opera – 50%.  Как уже говорилось, дальше в режиме простоя Chrome потреблял от 2 до 7% процессора. Но у Chrome наблюдается сильное преимущество по переключению контекста между потоками, хотя это не очень точно.</p>
<p align="left">Тут мне стало интересно, как поведет себя Chrome при открытии нескольких табов и окон. Методику я выбрал самую простую:</p>
<p>-    Для каждого браузера (Chrome, Firefox 2, Internet Explorer 7, Opera 9.5) открывается 10 пустых табов (то есть свежие инсталляции, без истории закладок и плагинов).<br />
-    Открывается 10 табов с одним и тем же ресурсом (я выбрал главную страницу Youtube)<br />
-    Открывается 10 отдельных окон с Youtube (окна с пустыми страницами я опустил, ничего особенного предварительные тесты не показали).<br />
-    Каждый тест повторяется 10 раз и берутся усредненные значения, если не окажется, что есть очевидные пики.Условия проведения замеров одинаковые для всех браузеров (Windows XP SP3, 32bit, Athlong 3500+, 1GB Dual RAM).В результате я получил 6 табличек cо значениями для физической и виртуальной памяти.<br />
Потребление физической памяти на пустой выглядело так, при открытии табов:</p>
<p align="right">Физическая память (MB)</p>
<p align="right"><img class="alignnone" title=" " src="http://alsedi.com/blog/wp-content/upload/fisical_mem_nulltab.png" alt="" width="707" height="536" /></p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="72" valign="top">Вкладки</td>
<td width="59" valign="top">1</td>
<td width="59" valign="top">2</td>
<td width="59" valign="top">3</td>
<td width="59" valign="top">4</td>
<td width="59" valign="top">5</td>
<td width="59" valign="top">6</td>
<td width="59" valign="top">7</td>
<td width="59" valign="top">8</td>
<td width="59" valign="top">9</td>
<td width="58" valign="top">10</td>
</tr>
<tr>
<td width="72" valign="top">Chrome</td>
<td width="59" valign="top">29*</td>
<td width="59" valign="top">33</td>
<td width="59" valign="top">33</td>
<td width="59" valign="top">35</td>
<td width="59" valign="top">36</td>
<td width="59" valign="top">38</td>
<td width="59" valign="top">38</td>
<td width="59" valign="top">39</td>
<td width="59" valign="top">40</td>
<td width="58" valign="top">42</td>
</tr>
<tr>
<td width="72" valign="top">Firefox</td>
<td width="59" valign="top">35</td>
<td width="59" valign="top">36</td>
<td width="59" valign="top">36</td>
<td width="59" valign="top">36</td>
<td width="59" valign="top">36</td>
<td width="59" valign="top">37</td>
<td width="59" valign="top">37</td>
<td width="59" valign="top">37</td>
<td width="59" valign="top">37</td>
<td width="58" valign="top">37</td>
</tr>
<tr>
<td width="72" valign="top">Internet Explorer</td>
<td width="59" valign="top">23</td>
<td width="59" valign="top">27</td>
<td width="59" valign="top">28</td>
<td width="59" valign="top">30</td>
<td width="59" valign="top">30</td>
<td width="59" valign="top">31</td>
<td width="59" valign="top">32</td>
<td width="59" valign="top">33</td>
<td width="59" valign="top">34</td>
<td width="58" valign="top">35</td>
</tr>
<tr>
<td width="72" valign="top">Opera</td>
<td width="59" valign="top">21</td>
<td width="59" valign="top">21</td>
<td width="59" valign="top">22</td>
<td width="59" valign="top">22</td>
<td width="59" valign="top">22</td>
<td width="59" valign="top">22</td>
<td width="59" valign="top">23</td>
<td width="59" valign="top">23</td>
<td width="59" valign="top">23</td>
<td width="58" valign="top">23</td>
</tr>
</tbody>
</table>
<p align="right">Виртуальная память (MB)</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="72" valign="top">Вкладки</td>
<td width="59" valign="top">1</td>
<td width="59" valign="top">2</td>
<td width="59" valign="top">3</td>
<td width="59" valign="top">4</td>
<td width="59" valign="top">5</td>
<td width="59" valign="top">6</td>
<td width="59" valign="top">7</td>
<td width="59" valign="top">8</td>
<td width="59" valign="top">9</td>
<td width="58" valign="top">10</td>
</tr>
<tr>
<td width="72" valign="top">Chrome</td>
<td width="59" valign="top">21**</td>
<td width="59" valign="top">23</td>
<td width="59" valign="top">25</td>
<td width="59" valign="top">27</td>
<td width="59" valign="top">29</td>
<td width="59" valign="top">32</td>
<td width="59" valign="top">33</td>
<td width="59" valign="top">33</td>
<td width="59" valign="top">33</td>
<td width="58" valign="top">39</td>
</tr>
<tr>
<td width="72" valign="top">Firefox</td>
<td width="59" valign="top">26</td>
<td width="59" valign="top">26</td>
<td width="59" valign="top">27</td>
<td width="59" valign="top">27</td>
<td width="59" valign="top">27</td>
<td width="59" valign="top">27</td>
<td width="59" valign="top">27</td>
<td width="59" valign="top">27</td>
<td width="59" valign="top">27</td>
<td width="58" valign="top">28</td>
</tr>
<tr>
<td width="72" valign="top">Internet Explorer</td>
<td width="59" valign="top">17</td>
<td width="59" valign="top">20</td>
<td width="59" valign="top">21</td>
<td width="59" valign="top">22</td>
<td width="59" valign="top">22</td>
<td width="59" valign="top">23</td>
<td width="59" valign="top">24</td>
<td width="59" valign="top">25</td>
<td width="59" valign="top">26</td>
<td width="58" valign="top">26</td>
</tr>
<tr>
<td width="72" valign="top">Opera</td>
<td width="59" valign="top">18</td>
<td width="59" valign="top">18</td>
<td width="59" valign="top">18</td>
<td width="59" valign="top">19</td>
<td width="59" valign="top">19</td>
<td width="59" valign="top">19</td>
<td width="59" valign="top">19</td>
<td width="59" valign="top">20</td>
<td width="59" valign="top">20</td>
<td width="58" valign="top">20</td>
</tr>
</tbody>
</table>
<p>А вот так память потреблялась при загрузке главной страницы Youtube, опять-таки 10 табов  в одном окне:</p>
<p align="right">Физическая память (MB)</p>
<p align="right"><img class="alignnone" title=" " src="http://alsedi.com/blog/wp-content/upload/fisical_mem_youtube.png" alt="" width="709" height="532" /></p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="72" valign="top">Вкладки</td>
<td width="59" valign="top">1</td>
<td width="59" valign="top">2</td>
<td width="59" valign="top">3</td>
<td width="59" valign="top">4</td>
<td width="59" valign="top">5</td>
<td width="59" valign="top">6</td>
<td width="59" valign="top">7</td>
<td width="59" valign="top">8</td>
<td width="59" valign="top">9</td>
<td width="58" valign="top">10</td>
</tr>
<tr>
<td width="72" valign="top">Chrome</td>
<td width="59" valign="top">40</td>
<td width="59" valign="top">80</td>
<td width="59" valign="top">101</td>
<td width="59" valign="top">122</td>
<td width="59" valign="top">149</td>
<td width="59" valign="top">157</td>
<td width="59" valign="top">165</td>
<td width="59" valign="top">187</td>
<td width="59" valign="top">207</td>
<td width="58" valign="top">252</td>
</tr>
<tr>
<td width="72" valign="top">Firefox</td>
<td width="59" valign="top">44</td>
<td width="59" valign="top">49</td>
<td width="59" valign="top">54</td>
<td width="59" valign="top">59</td>
<td width="59" valign="top">67</td>
<td width="59" valign="top">70</td>
<td width="59" valign="top">72</td>
<td width="59" valign="top">78</td>
<td width="59" valign="top">81</td>
<td width="58" valign="top">91</td>
</tr>
<tr>
<td width="72" valign="top">Internet Explorer</td>
<td width="59" valign="top">39</td>
<td width="59" valign="top">51</td>
<td width="59" valign="top">60</td>
<td width="59" valign="top">71</td>
<td width="59" valign="top">78</td>
<td width="59" valign="top">88</td>
<td width="59" valign="top">99</td>
<td width="59" valign="top">108</td>
<td width="59" valign="top">115</td>
<td width="58" valign="top">127</td>
</tr>
<tr>
<td width="72" valign="top">Opera</td>
<td width="59" valign="top">35</td>
<td width="59" valign="top">39</td>
<td width="59" valign="top">47</td>
<td width="59" valign="top">53</td>
<td width="59" valign="top">58</td>
<td width="59" valign="top">63</td>
<td width="59" valign="top">70</td>
<td width="59" valign="top">77</td>
<td width="59" valign="top">84</td>
<td width="58" valign="top">89</td>
</tr>
</tbody>
</table>
<p align="right">Виртуальная память (MB)</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="72" valign="top">Вкладки</td>
<td width="59" valign="top">1</td>
<td width="59" valign="top">2</td>
<td width="59" valign="top">3</td>
<td width="59" valign="top">4</td>
<td width="59" valign="top">5</td>
<td width="59" valign="top">6</td>
<td width="59" valign="top">7</td>
<td width="59" valign="top">8</td>
<td width="59" valign="top">9</td>
<td width="58" valign="top">10</td>
</tr>
<tr>
<td width="72" valign="top">Chrome</td>
<td width="59" valign="top">32</td>
<td width="59" valign="top">61</td>
<td width="59" valign="top">76</td>
<td width="59" valign="top">89</td>
<td width="59" valign="top">107</td>
<td width="59" valign="top">117</td>
<td width="59" valign="top">123</td>
<td width="59" valign="top">139</td>
<td width="59" valign="top">154</td>
<td width="58" valign="top">193</td>
</tr>
<tr>
<td width="72" valign="top">Firefox</td>
<td width="59" valign="top">35</td>
<td width="59" valign="top">39</td>
<td width="59" valign="top">44</td>
<td width="59" valign="top">50</td>
<td width="59" valign="top">59</td>
<td width="59" valign="top">61</td>
<td width="59" valign="top">63</td>
<td width="59" valign="top">68</td>
<td width="59" valign="top">72</td>
<td width="58" valign="top">82</td>
</tr>
<tr>
<td width="72" valign="top">Internet Explorer</td>
<td width="59" valign="top">31</td>
<td width="59" valign="top">42</td>
<td width="59" valign="top">51</td>
<td width="59" valign="top">62</td>
<td width="59" valign="top">70</td>
<td width="59" valign="top">81</td>
<td width="59" valign="top">91</td>
<td width="59" valign="top">99</td>
<td width="59" valign="top">108</td>
<td width="58" valign="top">118</td>
</tr>
<tr>
<td width="72" valign="top">Opera</td>
<td width="59" valign="top">32</td>
<td width="59" valign="top">37</td>
<td width="59" valign="top">44</td>
<td width="59" valign="top">51</td>
<td width="59" valign="top">56</td>
<td width="59" valign="top">61</td>
<td width="59" valign="top">68</td>
<td width="59" valign="top">75</td>
<td width="59" valign="top">82</td>
<td width="58" valign="top">87</td>
</tr>
</tbody>
</table>
<p>Распределение памяти при открытии десяти табов с Youtube оказалось следующим:</p>
<ul>
<li><strong>Chrome</strong> – нерегулярно до 30% CPU, по разным процессам.</li>
<li><strong>Firefox</strong> – постоянное использование около 20% с пиками до 50%.</li>
<li><strong>Internet Explorer</strong> – от 20% до 50%</li>
<li><strong>Opera</strong> – использование CPU колебалось в районе 30%</li>
</ul>
<p>Интересно так же то, что распределение памяти между процессами было неоднородным и отличалось в пределах до 5 мегабайт для табов, плюс два процесса по 50 мегабайт (плюс минус 3). В отличие от Firefox и Internet Explorer, память не росла безостановочно.<br />
Распределение памяти в случае 10 разных окон.</p>
<p align="right">Физическая память (MB)</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="72" valign="top">Окна</td>
<td width="59" valign="top">1</td>
<td width="59" valign="top">2</td>
<td width="59" valign="top">3</td>
<td width="59" valign="top">4</td>
<td width="59" valign="top">5</td>
<td width="59" valign="top">6</td>
<td width="59" valign="top">7</td>
<td width="59" valign="top">8</td>
<td width="59" valign="top">9</td>
<td width="58" valign="top">10</td>
</tr>
<tr>
<td width="72" valign="top">Chrome</td>
<td width="59" valign="top">41</td>
<td width="59" valign="top">80</td>
<td width="59" valign="top">101</td>
<td width="59" valign="top">125</td>
<td width="59" valign="top">138</td>
<td width="59" valign="top">145</td>
<td width="59" valign="top">167</td>
<td width="59" valign="top">179</td>
<td width="59" valign="top">204</td>
<td width="58" valign="top">224</td>
</tr>
<tr>
<td width="72" valign="top">Firefox</td>
<td width="59" valign="top">44</td>
<td width="59" valign="top">51</td>
<td width="59" valign="top">59</td>
<td width="59" valign="top">66</td>
<td width="59" valign="top">78</td>
<td width="59" valign="top">83</td>
<td width="59" valign="top">92</td>
<td width="59" valign="top">102</td>
<td width="59" valign="top">107</td>
<td width="58" valign="top">114</td>
</tr>
<tr>
<td width="72" valign="top">Internet Explorer</td>
<td width="59" valign="top">39</td>
<td width="59" valign="top">83</td>
<td width="59" valign="top">123</td>
<td width="59" valign="top">165</td>
<td width="59" valign="top">204</td>
<td width="59" valign="top">246</td>
<td width="59" valign="top">288</td>
<td width="59" valign="top">330</td>
<td width="59" valign="top">373</td>
<td width="58" valign="top">414</td>
</tr>
<tr>
<td width="72" valign="top">Opera</td>
<td width="59" valign="top">34</td>
<td width="59" valign="top">42</td>
<td width="59" valign="top">49</td>
<td width="59" valign="top">54</td>
<td width="59" valign="top">61</td>
<td width="59" valign="top">69</td>
<td width="59" valign="top">77</td>
<td width="59" valign="top">83</td>
<td width="59" valign="top">91</td>
<td width="58" valign="top">95</td>
</tr>
</tbody>
</table>
<p align="right">Виртуальная память (MB)</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="72" valign="top">Окна</td>
<td width="59" valign="top">1</td>
<td width="59" valign="top">2</td>
<td width="59" valign="top">3</td>
<td width="59" valign="top">4</td>
<td width="59" valign="top">5</td>
<td width="59" valign="top">6</td>
<td width="59" valign="top">7</td>
<td width="59" valign="top">8</td>
<td width="59" valign="top">9</td>
<td width="58" valign="top">10</td>
</tr>
<tr>
<td width="72" valign="top">Chrome</td>
<td width="59" valign="top">33</td>
<td width="59" valign="top">62</td>
<td width="59" valign="top">78</td>
<td width="59" valign="top">94</td>
<td width="59" valign="top">102</td>
<td width="59" valign="top">110</td>
<td width="59" valign="top">125</td>
<td width="59" valign="top">131</td>
<td width="59" valign="top">150</td>
<td width="58" valign="top">165</td>
</tr>
<tr>
<td width="72" valign="top">Firefox</td>
<td width="59" valign="top">34</td>
<td width="59" valign="top">42</td>
<td width="59" valign="top">49</td>
<td width="59" valign="top">56</td>
<td width="59" valign="top">68</td>
<td width="59" valign="top">73</td>
<td width="59" valign="top">83</td>
<td width="59" valign="top">92</td>
<td width="59" valign="top">98</td>
<td width="58" valign="top">104</td>
</tr>
<tr>
<td width="72" valign="top">Internet Explorer</td>
<td width="59" valign="top">32</td>
<td width="59" valign="top">37</td>
<td width="59" valign="top">100</td>
<td width="59" valign="top">132</td>
<td width="59" valign="top">166</td>
<td width="59" valign="top">200</td>
<td width="59" valign="top">234</td>
<td width="59" valign="top">267</td>
<td width="59" valign="top">300</td>
<td width="58" valign="top">332</td>
</tr>
<tr>
<td width="72" valign="top">Opera</td>
<td width="59" valign="top">31</td>
<td width="59" valign="top">40</td>
<td width="59" valign="top">46</td>
<td width="59" valign="top">53</td>
<td width="59" valign="top">59</td>
<td width="59" valign="top">67</td>
<td width="59" valign="top">75</td>
<td width="59" valign="top">81</td>
<td width="59" valign="top">90</td>
<td width="58" valign="top">93</td>
</tr>
</tbody>
</table>
<p>В общем и целом Chrome показал себя довольно прожорливым браузером по памяти (но в случае с окнами &#8211; намного лучше, чем Internet Explorer), но наиболее нетребовательным к процессору. При теперешнем росте объемов памяти, в принципе, не существенно. Браузер действительно должен работать быстрее, чем остальные. Пока память не закончится, конечно.</p>
<p>Но всё-таки, реально отдельные процессы создает только Internet Explorer, в Chrome (повторюсь), так или иначе всё завязано на главный процесс ядра.</p>
<p>По стандартам всё очень даже неплохо:</p>
<ul><strong><a href="http://acid3.acidtests.org/" target="blank">Acid3</a></strong></p>
<li>Chrome – 79</li>
<li>Opera 9.5 – 84</li>
<li>Firefox 2 – 52</li>
<li>Firefox 3 &#8211; 71</li>
<li>Internet Explorer 7.0 – я не понял сколько, картинка была сбита полностью</li>
</ul>
<p><strong><a href="http://www.webstandards.org/files/acid2/test.html" target="blank">Acid2</a></strong><br />
Chrome, Firefox 3, Opera 9.5 – прошли.</p>
<p>По сегодняшним меркам очень приличный результат, но люди говорят, что некоторые страницы разъезжаются. Так что если Chrome займёт существенную долю рынка веб разработчикам и верстальщикам всё-таки придется попотеть. Впрочем, и тестировщикам тоже (меж тем Selenium, например, все еще не поддерживает Chrome).</p>
<p>Закончу эту часть рассказа такой вот картинкой :)</p>
<p><img src="http://alsedi.com/blog/wp-content/upload/page-error.png" alt="" /></p>
<p><a href="http://alsedi.com/blog/chast-2-google-chrome-dlya-razrabotchikov/">Часть 2: Google Chrome для разработчиков</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.alsedi.com/chast1-google-chrome/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

